Mercurial > hg
annotate contrib/hgk @ 280:a69c3b2957d1
Mark the usual things executable
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Mark the usual things executable
manifest hash: e55dde46fd1a97ce338c1ac71278b67ca9d96bf7
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.0 (GNU/Linux)
iD8DBQFCpz5RywK+sNU5EO8RAnypAJwLpjrQ09nMSJUELtCondHI0fvuVACfQu2J
mFi9D3L9ULGO457NWB4h3kY=
=3bcD
-----END PGP SIGNATURE-----
author | mpm@selenic.com |
---|---|
date | Wed, 08 Jun 2005 10:52:01 -0800 |
parents | 5da941efbb52 |
children | 18c9566ad717 |
rev | line source |
---|---|
267 | 1 #!/bin/sh |
2 # Tcl ignores the next line -*- tcl -*- \ | |
3 exec 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.20 $ | |
11 | |
12 proc readfullcommits {rargs} { | |
13 global commits commfd phase canv mainfont curcommit allcommitstate | |
14 if {$rargs == {}} { | |
15 set rargs HEAD | |
16 } | |
17 set commits {} | |
18 set curcommit {} | |
19 set allcommitstate none | |
20 set phase getcommits | |
21 if [catch {set commfd [open "|hgit rev-list -c $rargs" r]} err] { | |
22 puts stderr "Error executing hgit rev-list: $err" | |
23 exit 1 | |
24 } | |
25 fconfigure $commfd -blocking 0 | |
26 fileevent $commfd readable "getallcommitline $commfd" | |
27 $canv delete all | |
28 $canv create text 3 3 -anchor nw -text "Reading all commits..." \ | |
29 -font $mainfont -tags textitems | |
30 } | |
31 | |
32 proc getcommitline {commfd} { | |
33 global commits parents cdate nparents children nchildren | |
34 set n [gets $commfd line] | |
35 if {$n < 0} { | |
36 if {![eof $commfd]} return | |
37 # this works around what is apparently a bug in Tcl... | |
38 fconfigure $commfd -blocking 1 | |
39 if {![catch {close $commfd} err]} { | |
40 after idle readallcommits | |
41 return | |
42 } | |
43 if {[string range $err 0 4] == "usage"} { | |
44 set err "\ | |
45 Gitk: error reading commits: bad arguments to hgit rev-list.\n\ | |
46 (Note: arguments to gitk are passed to hgit rev-list\ | |
47 to allow selection of commits to be displayed.)" | |
48 } else { | |
49 set err "Error reading commits: $err" | |
50 } | |
51 error_popup $err | |
52 exit 1 | |
53 } | |
54 if {![regexp {^[0-9a-f]{40}$} $line]} { | |
55 error_popup "Can't parse hgit rev-tree output: {$line}" | |
56 exit 1 | |
57 } | |
58 lappend commits $line | |
59 } | |
60 | |
61 proc readallcommits {} { | |
62 global commits | |
63 foreach id $commits { | |
64 readcommit $id | |
65 update | |
66 } | |
67 drawgraph | |
68 } | |
69 | |
70 proc readonecommit {id contents} { | |
71 global commitinfo children nchildren parents nparents cdate | |
72 set inhdr 1 | |
73 set comment {} | |
74 set headline {} | |
75 set auname {} | |
76 set audate {} | |
77 set comname {} | |
78 set comdate {} | |
79 if {![info exists nchildren($id)]} { | |
80 set children($id) {} | |
81 set nchildren($id) 0 | |
82 } | |
83 set parents($id) {} | |
84 set nparents($id) 0 | |
85 foreach line [split $contents "\n"] { | |
86 if {$inhdr} { | |
87 if {$line == {}} { | |
88 set inhdr 0 | |
89 } else { | |
90 set tag [lindex $line 0] | |
91 if {$tag == "parent"} { | |
92 set p [lindex $line 1] | |
93 if {![info exists nchildren($p)]} { | |
94 set children($p) {} | |
95 set nchildren($p) 0 | |
96 } | |
97 lappend parents($id) $p | |
98 incr nparents($id) | |
99 if {[lsearch -exact $children($p) $id] < 0} { | |
100 lappend children($p) $id | |
101 incr nchildren($p) | |
102 } | |
103 } elseif {$tag == "author"} { | |
104 set x [expr {[llength $line] - 2}] | |
105 set audate [lindex $line $x] | |
106 set auname [lrange $line 1 [expr {$x - 1}]] | |
107 } elseif {$tag == "committer"} { | |
108 set x [expr {[llength $line] - 2}] | |
109 set comdate [lindex $line $x] | |
110 set comname [lrange $line 1 [expr {$x - 1}]] | |
111 } | |
112 } | |
113 } else { | |
114 if {$comment == {}} { | |
115 set headline $line | |
116 } else { | |
117 append comment "\n" | |
118 } | |
119 append comment $line | |
120 } | |
121 } | |
122 if {$audate != {}} { | |
123 set audate [clock format $audate -format "%Y-%m-%d %H:%M:%S"] | |
124 } | |
125 if {$comdate != {}} { | |
126 set cdate($id) $comdate | |
127 set comdate [clock format $comdate -format "%Y-%m-%d %H:%M:%S"] | |
128 } | |
129 set commitinfo($id) [list $headline $auname $audate \ | |
130 $comname $comdate $comment] | |
131 } | |
132 | |
133 proc getallcommitline {commfd} { | |
134 global commits allcommitstate curcommit curcommitid | |
135 set n [gets $commfd line] | |
136 set s "\n" | |
137 if {$n < 0} { | |
138 if {![eof $commfd]} return | |
139 # this works around what is apparently a bug in Tcl... | |
140 fconfigure $commfd -blocking 1 | |
141 if {![catch {close $commfd} err]} { | |
142 after idle drawgraph | |
143 return | |
144 } | |
145 if {[string range $err 0 4] == "usage"} { | |
146 set err "\ | |
147 Gitk: error reading commits: bad arguments to hgit rev-list.\n\ | |
148 (Note: arguments to gitk are passed to hgit rev-list\ | |
149 to allow selection of commits to be displayed.)" | |
150 } else { | |
151 set err "Error reading commits: $err" | |
152 } | |
153 error_popup $err | |
154 exit 1 | |
155 } | |
156 if {[string range $line 0 1] != " "} { | |
157 if {$allcommitstate == "indent"} { | |
158 readonecommit $curcommitid $curcommit | |
159 } | |
160 if {$allcommitstate == "start"} { | |
161 set curcommit $curcommit$line$s | |
162 set allcommitstate "indent" | |
163 } else { | |
164 set curcommitid $line | |
165 set curcommit {} | |
166 set allcommitstate "start" | |
167 lappend commits $line | |
168 } | |
169 } else { | |
170 set d [string range $line 2 end] | |
171 set curcommit $curcommit$d$s | |
172 } | |
173 } | |
174 | |
175 proc getcommits {rargs} { | |
176 global commits commfd phase canv mainfont | |
177 if {$rargs == {}} { | |
178 set rargs HEAD | |
179 } | |
180 set commits {} | |
181 set phase getcommits | |
182 if [catch {set commfd [open "|hgit rev-list $rargs" r]} err] { | |
183 puts stderr "Error executing hgit rev-list: $err" | |
184 exit 1 | |
185 } | |
186 fconfigure $commfd -blocking 0 | |
187 fileevent $commfd readable "getcommitline $commfd" | |
188 $canv delete all | |
189 $canv create text 3 3 -anchor nw -text "Reading commits..." \ | |
190 -font $mainfont -tags textitems | |
191 } | |
192 | |
193 proc readcommit {id} { | |
194 global commitinfo children nchildren parents nparents cdate | |
195 set inhdr 1 | |
196 set comment {} | |
197 set headline {} | |
198 set auname {} | |
199 set audate {} | |
200 set comname {} | |
201 set comdate {} | |
202 if {![info exists nchildren($id)]} { | |
203 set children($id) {} | |
204 set nchildren($id) 0 | |
205 } | |
206 set parents($id) {} | |
207 set nparents($id) 0 | |
208 if [catch {set contents [exec hgit cat-file commit $id]}] return | |
209 readonecommit $id $contents | |
210 } | |
211 | |
212 proc readrefs {} { | |
213 global tagids idtags | |
214 set tags [glob -nocomplain -types f .git/refs/tags/*] | |
215 foreach f $tags { | |
216 catch { | |
217 set fd [open $f r] | |
218 set line [read $fd] | |
219 if {[regexp {^[0-9a-f]{40}} $line id]} { | |
220 set contents [split [exec hgit cat-file tag $id] "\n"] | |
221 set obj {} | |
222 set type {} | |
223 set tag {} | |
224 foreach l $contents { | |
225 if {$l == {}} break | |
226 switch -- [lindex $l 0] { | |
227 "object" {set obj [lindex $l 1]} | |
228 "type" {set type [lindex $l 1]} | |
229 "tag" {set tag [string range $l 4 end]} | |
230 } | |
231 } | |
232 if {$obj != {} && $type == "commit" && $tag != {}} { | |
233 set tagids($tag) $obj | |
234 lappend idtags($obj) $tag | |
235 } | |
236 } | |
237 } | |
238 } | |
239 } | |
240 | |
241 proc error_popup msg { | |
242 set w .error | |
243 toplevel $w | |
244 wm transient $w . | |
245 message $w.m -text $msg -justify center -aspect 400 | |
246 pack $w.m -side top -fill x -padx 20 -pady 20 | |
247 button $w.ok -text OK -command "destroy $w" | |
248 pack $w.ok -side bottom -fill x | |
249 bind $w <Visibility> "grab $w; focus $w" | |
250 tkwait window $w | |
251 } | |
252 | |
253 proc makewindow {} { | |
254 global canv canv2 canv3 linespc charspc ctext cflist textfont | |
255 global findtype findloc findstring fstring geometry | |
256 global entries sha1entry sha1string sha1but | |
257 | |
258 menu .bar | |
259 .bar add cascade -label "File" -menu .bar.file | |
260 menu .bar.file | |
261 .bar.file add command -label "Quit" -command doquit | |
262 menu .bar.help | |
263 .bar add cascade -label "Help" -menu .bar.help | |
264 .bar.help add command -label "About gitk" -command about | |
265 . configure -menu .bar | |
266 | |
267 if {![info exists geometry(canv1)]} { | |
268 set geometry(canv1) [expr 45 * $charspc] | |
269 set geometry(canv2) [expr 30 * $charspc] | |
270 set geometry(canv3) [expr 15 * $charspc] | |
271 set geometry(canvh) [expr 25 * $linespc + 4] | |
272 set geometry(ctextw) 80 | |
273 set geometry(ctexth) 30 | |
274 set geometry(cflistw) 30 | |
275 } | |
276 panedwindow .ctop -orient vertical | |
277 if {[info exists geometry(width)]} { | |
278 .ctop conf -width $geometry(width) -height $geometry(height) | |
279 set texth [expr {$geometry(height) - $geometry(canvh) - 56}] | |
280 set geometry(ctexth) [expr {($texth - 8) / | |
281 [font metrics $textfont -linespace]}] | |
282 } | |
283 frame .ctop.top | |
284 frame .ctop.top.bar | |
285 pack .ctop.top.bar -side bottom -fill x | |
286 set cscroll .ctop.top.csb | |
287 scrollbar $cscroll -command {allcanvs yview} -highlightthickness 0 | |
288 pack $cscroll -side right -fill y | |
289 panedwindow .ctop.top.clist -orient horizontal -sashpad 0 -handlesize 4 | |
290 pack .ctop.top.clist -side top -fill both -expand 1 | |
291 .ctop add .ctop.top | |
292 set canv .ctop.top.clist.canv | |
293 canvas $canv -height $geometry(canvh) -width $geometry(canv1) \ | |
294 -bg white -bd 0 \ | |
295 -yscrollincr $linespc -yscrollcommand "$cscroll set" | |
296 .ctop.top.clist add $canv | |
297 set canv2 .ctop.top.clist.canv2 | |
298 canvas $canv2 -height $geometry(canvh) -width $geometry(canv2) \ | |
299 -bg white -bd 0 -yscrollincr $linespc | |
300 .ctop.top.clist add $canv2 | |
301 set canv3 .ctop.top.clist.canv3 | |
302 canvas $canv3 -height $geometry(canvh) -width $geometry(canv3) \ | |
303 -bg white -bd 0 -yscrollincr $linespc | |
304 .ctop.top.clist add $canv3 | |
305 bind .ctop.top.clist <Configure> {resizeclistpanes %W %w} | |
306 | |
307 set sha1entry .ctop.top.bar.sha1 | |
308 set entries $sha1entry | |
309 set sha1but .ctop.top.bar.sha1label | |
310 button $sha1but -text "SHA1 ID: " -state disabled -relief flat \ | |
311 -command gotocommit -width 8 | |
312 $sha1but conf -disabledforeground [$sha1but cget -foreground] | |
313 pack .ctop.top.bar.sha1label -side left | |
314 entry $sha1entry -width 40 -font $textfont -textvariable sha1string | |
315 trace add variable sha1string write sha1change | |
316 pack $sha1entry -side left -pady 2 | |
317 button .ctop.top.bar.findbut -text "Find" -command dofind | |
318 pack .ctop.top.bar.findbut -side left | |
319 set findstring {} | |
320 set fstring .ctop.top.bar.findstring | |
321 lappend entries $fstring | |
322 entry $fstring -width 30 -font $textfont -textvariable findstring | |
323 pack $fstring -side left -expand 1 -fill x | |
324 set findtype Exact | |
325 tk_optionMenu .ctop.top.bar.findtype findtype Exact IgnCase Regexp | |
326 set findloc "All fields" | |
327 tk_optionMenu .ctop.top.bar.findloc findloc "All fields" Headline \ | |
328 Comments Author Committer | |
329 pack .ctop.top.bar.findloc -side right | |
330 pack .ctop.top.bar.findtype -side right | |
331 | |
332 panedwindow .ctop.cdet -orient horizontal | |
333 .ctop add .ctop.cdet | |
334 frame .ctop.cdet.left | |
335 set ctext .ctop.cdet.left.ctext | |
336 text $ctext -bg white -state disabled -font $textfont \ | |
337 -width $geometry(ctextw) -height $geometry(ctexth) \ | |
338 -yscrollcommand ".ctop.cdet.left.sb set" | |
339 scrollbar .ctop.cdet.left.sb -command "$ctext yview" | |
340 pack .ctop.cdet.left.sb -side right -fill y | |
341 pack $ctext -side left -fill both -expand 1 | |
342 .ctop.cdet add .ctop.cdet.left | |
343 | |
344 $ctext tag conf filesep -font [concat $textfont bold] | |
345 $ctext tag conf hunksep -back blue -fore white | |
346 $ctext tag conf d0 -back "#ff8080" | |
347 $ctext tag conf d1 -back green | |
348 $ctext tag conf found -back yellow | |
349 | |
350 frame .ctop.cdet.right | |
351 set cflist .ctop.cdet.right.cfiles | |
352 listbox $cflist -bg white -selectmode extended -width $geometry(cflistw) \ | |
353 -yscrollcommand ".ctop.cdet.right.sb set" | |
354 scrollbar .ctop.cdet.right.sb -command "$cflist yview" | |
355 pack .ctop.cdet.right.sb -side right -fill y | |
356 pack $cflist -side left -fill both -expand 1 | |
357 .ctop.cdet add .ctop.cdet.right | |
358 bind .ctop.cdet <Configure> {resizecdetpanes %W %w} | |
359 | |
360 pack .ctop -side top -fill both -expand 1 | |
361 | |
362 bindall <1> {selcanvline %x %y} | |
363 bindall <B1-Motion> {selcanvline %x %y} | |
364 bindall <ButtonRelease-4> "allcanvs yview scroll -5 units" | |
365 bindall <ButtonRelease-5> "allcanvs yview scroll 5 units" | |
366 bindall <2> "allcanvs scan mark 0 %y" | |
367 bindall <B2-Motion> "allcanvs scan dragto 0 %y" | |
368 bind . <Key-Up> "selnextline -1" | |
369 bind . <Key-Down> "selnextline 1" | |
370 bind . <Key-Prior> "allcanvs yview scroll -1 pages" | |
371 bind . <Key-Next> "allcanvs yview scroll 1 pages" | |
372 bindkey <Key-Delete> "$ctext yview scroll -1 pages" | |
373 bindkey <Key-BackSpace> "$ctext yview scroll -1 pages" | |
374 bindkey <Key-space> "$ctext yview scroll 1 pages" | |
375 bindkey p "selnextline -1" | |
376 bindkey n "selnextline 1" | |
377 bindkey b "$ctext yview scroll -1 pages" | |
378 bindkey d "$ctext yview scroll 18 units" | |
379 bindkey u "$ctext yview scroll -18 units" | |
380 bindkey / findnext | |
381 bindkey ? findprev | |
382 bindkey f nextfile | |
383 bind . <Control-q> doquit | |
384 bind . <Control-f> dofind | |
385 bind . <Control-g> findnext | |
386 bind . <Control-r> findprev | |
387 bind . <Control-equal> {incrfont 1} | |
388 bind . <Control-KP_Add> {incrfont 1} | |
389 bind . <Control-minus> {incrfont -1} | |
390 bind . <Control-KP_Subtract> {incrfont -1} | |
391 bind $cflist <<ListboxSelect>> listboxsel | |
392 bind . <Destroy> {savestuff %W} | |
393 bind . <Button-1> "click %W" | |
394 bind $fstring <Key-Return> dofind | |
395 bind $sha1entry <Key-Return> gotocommit | |
396 } | |
397 | |
398 # when we make a key binding for the toplevel, make sure | |
399 # it doesn't get triggered when that key is pressed in the | |
400 # find string entry widget. | |
401 proc bindkey {ev script} { | |
402 global entries | |
403 bind . $ev $script | |
404 set escript [bind Entry $ev] | |
405 if {$escript == {}} { | |
406 set escript [bind Entry <Key>] | |
407 } | |
408 foreach e $entries { | |
409 bind $e $ev "$escript; break" | |
410 } | |
411 } | |
412 | |
413 # set the focus back to the toplevel for any click outside | |
414 # the entry widgets | |
415 proc click {w} { | |
416 global entries | |
417 foreach e $entries { | |
418 if {$w == $e} return | |
419 } | |
420 focus . | |
421 } | |
422 | |
423 proc savestuff {w} { | |
424 global canv canv2 canv3 ctext cflist mainfont textfont | |
425 global stuffsaved | |
426 if {$stuffsaved} return | |
427 if {![winfo viewable .]} return | |
428 catch { | |
429 set f [open "~/.gitk-new" w] | |
430 puts $f "set mainfont {$mainfont}" | |
431 puts $f "set textfont {$textfont}" | |
432 puts $f "set geometry(width) [winfo width .ctop]" | |
433 puts $f "set geometry(height) [winfo height .ctop]" | |
434 puts $f "set geometry(canv1) [expr [winfo width $canv]-2]" | |
435 puts $f "set geometry(canv2) [expr [winfo width $canv2]-2]" | |
436 puts $f "set geometry(canv3) [expr [winfo width $canv3]-2]" | |
437 puts $f "set geometry(canvh) [expr [winfo height $canv]-2]" | |
438 set wid [expr {([winfo width $ctext] - 8) \ | |
439 / [font measure $textfont "0"]}] | |
440 puts $f "set geometry(ctextw) $wid" | |
441 set wid [expr {([winfo width $cflist] - 11) \ | |
442 / [font measure [$cflist cget -font] "0"]}] | |
443 puts $f "set geometry(cflistw) $wid" | |
444 close $f | |
445 file rename -force "~/.gitk-new" "~/.gitk" | |
446 } | |
447 set stuffsaved 1 | |
448 } | |
449 | |
450 proc resizeclistpanes {win w} { | |
451 global oldwidth | |
452 if [info exists oldwidth($win)] { | |
453 set s0 [$win sash coord 0] | |
454 set s1 [$win sash coord 1] | |
455 if {$w < 60} { | |
456 set sash0 [expr {int($w/2 - 2)}] | |
457 set sash1 [expr {int($w*5/6 - 2)}] | |
458 } else { | |
459 set factor [expr {1.0 * $w / $oldwidth($win)}] | |
460 set sash0 [expr {int($factor * [lindex $s0 0])}] | |
461 set sash1 [expr {int($factor * [lindex $s1 0])}] | |
462 if {$sash0 < 30} { | |
463 set sash0 30 | |
464 } | |
465 if {$sash1 < $sash0 + 20} { | |
466 set sash1 [expr $sash0 + 20] | |
467 } | |
468 if {$sash1 > $w - 10} { | |
469 set sash1 [expr $w - 10] | |
470 if {$sash0 > $sash1 - 20} { | |
471 set sash0 [expr $sash1 - 20] | |
472 } | |
473 } | |
474 } | |
475 $win sash place 0 $sash0 [lindex $s0 1] | |
476 $win sash place 1 $sash1 [lindex $s1 1] | |
477 } | |
478 set oldwidth($win) $w | |
479 } | |
480 | |
481 proc resizecdetpanes {win w} { | |
482 global oldwidth | |
483 if [info exists oldwidth($win)] { | |
484 set s0 [$win sash coord 0] | |
485 if {$w < 60} { | |
486 set sash0 [expr {int($w*3/4 - 2)}] | |
487 } else { | |
488 set factor [expr {1.0 * $w / $oldwidth($win)}] | |
489 set sash0 [expr {int($factor * [lindex $s0 0])}] | |
490 if {$sash0 < 45} { | |
491 set sash0 45 | |
492 } | |
493 if {$sash0 > $w - 15} { | |
494 set sash0 [expr $w - 15] | |
495 } | |
496 } | |
497 $win sash place 0 $sash0 [lindex $s0 1] | |
498 } | |
499 set oldwidth($win) $w | |
500 } | |
501 | |
502 proc allcanvs args { | |
503 global canv canv2 canv3 | |
504 eval $canv $args | |
505 eval $canv2 $args | |
506 eval $canv3 $args | |
507 } | |
508 | |
509 proc bindall {event action} { | |
510 global canv canv2 canv3 | |
511 bind $canv $event $action | |
512 bind $canv2 $event $action | |
513 bind $canv3 $event $action | |
514 } | |
515 | |
516 proc about {} { | |
517 set w .about | |
518 if {[winfo exists $w]} { | |
519 raise $w | |
520 return | |
521 } | |
522 toplevel $w | |
523 wm title $w "About gitk" | |
524 message $w.m -text { | |
525 Gitk version 1.1 | |
526 | |
527 Copyright © 2005 Paul Mackerras | |
528 | |
529 Use and redistribute under the terms of the GNU General Public License | |
530 | |
531 (CVS $Revision: 1.20 $)} \ | |
532 -justify center -aspect 400 | |
533 pack $w.m -side top -fill x -padx 20 -pady 20 | |
534 button $w.ok -text Close -command "destroy $w" | |
535 pack $w.ok -side bottom | |
536 } | |
537 | |
538 proc truncatetofit {str width font} { | |
539 if {[font measure $font $str] <= $width} { | |
540 return $str | |
541 } | |
542 set best 0 | |
543 set bad [string length $str] | |
544 set tmp $str | |
545 while {$best < $bad - 1} { | |
546 set try [expr {int(($best + $bad) / 2)}] | |
547 set tmp "[string range $str 0 [expr $try-1]]..." | |
548 if {[font measure $font $tmp] <= $width} { | |
549 set best $try | |
550 } else { | |
551 set bad $try | |
552 } | |
553 } | |
554 return $tmp | |
555 } | |
556 | |
557 proc assigncolor {id} { | |
558 global commitinfo colormap commcolors colors nextcolor | |
559 global colorbycommitter | |
560 global parents nparents children nchildren | |
561 if [info exists colormap($id)] return | |
562 set ncolors [llength $colors] | |
563 if {$colorbycommitter} { | |
564 if {![info exists commitinfo($id)]} { | |
565 readcommit $id | |
566 } | |
567 set comm [lindex $commitinfo($id) 3] | |
568 if {![info exists commcolors($comm)]} { | |
569 set commcolors($comm) [lindex $colors $nextcolor] | |
570 if {[incr nextcolor] >= $ncolors} { | |
571 set nextcolor 0 | |
572 } | |
573 } | |
574 set colormap($id) $commcolors($comm) | |
575 } else { | |
576 if {$nparents($id) == 1 && $nchildren($id) == 1} { | |
577 set child [lindex $children($id) 0] | |
578 if {[info exists colormap($child)] | |
579 && $nparents($child) == 1} { | |
580 set colormap($id) $colormap($child) | |
581 return | |
582 } | |
583 } | |
584 set badcolors {} | |
585 foreach child $children($id) { | |
586 if {[info exists colormap($child)] | |
587 && [lsearch -exact $badcolors $colormap($child)] < 0} { | |
588 lappend badcolors $colormap($child) | |
589 } | |
590 if {[info exists parents($child)]} { | |
591 foreach p $parents($child) { | |
592 if {[info exists colormap($p)] | |
593 && [lsearch -exact $badcolors $colormap($p)] < 0} { | |
594 lappend badcolors $colormap($p) | |
595 } | |
596 } | |
597 } | |
598 } | |
599 if {[llength $badcolors] >= $ncolors} { | |
600 set badcolors {} | |
601 } | |
602 for {set i 0} {$i <= $ncolors} {incr i} { | |
603 set c [lindex $colors $nextcolor] | |
604 if {[incr nextcolor] >= $ncolors} { | |
605 set nextcolor 0 | |
606 } | |
607 if {[lsearch -exact $badcolors $c]} break | |
608 } | |
609 set colormap($id) $c | |
610 } | |
611 } | |
612 | |
613 proc drawgraph {} { | |
614 global parents children nparents nchildren commits | |
615 global canv canv2 canv3 mainfont namefont canvx0 canvy0 canvy linespc | |
616 global datemode cdate | |
617 global lineid linehtag linentag linedtag commitinfo | |
618 global nextcolor colormap numcommits | |
619 global stopped phase redisplaying selectedline idtags idline | |
620 | |
621 allcanvs delete all | |
622 set start {} | |
623 foreach id [array names nchildren] { | |
624 if {$nchildren($id) == 0} { | |
625 lappend start $id | |
626 } | |
627 set ncleft($id) $nchildren($id) | |
628 if {![info exists nparents($id)]} { | |
629 set nparents($id) 0 | |
630 } | |
631 } | |
632 if {$start == {}} { | |
633 error_popup "Gitk: ERROR: No starting commits found" | |
634 exit 1 | |
635 } | |
636 | |
637 set nextcolor 0 | |
638 foreach id $start { | |
639 assigncolor $id | |
640 } | |
641 set todo $start | |
642 set level [expr [llength $todo] - 1] | |
643 set y2 $canvy0 | |
644 set nullentry -1 | |
645 set lineno -1 | |
646 set numcommits 0 | |
647 set phase drawgraph | |
648 set lthickness [expr {($linespc / 9) + 1}] | |
649 while 1 { | |
650 set canvy $y2 | |
651 allcanvs conf -scrollregion \ | |
652 [list 0 0 0 [expr $canvy + 0.5 * $linespc + 2]] | |
653 update | |
654 if {$stopped} break | |
655 incr numcommits | |
656 incr lineno | |
657 set nlines [llength $todo] | |
658 set id [lindex $todo $level] | |
659 set lineid($lineno) $id | |
660 set idline($id) $lineno | |
661 set actualparents {} | |
662 set ofill white | |
663 if {[info exists parents($id)]} { | |
664 foreach p $parents($id) { | |
665 if {[info exists ncleft($p)]} { | |
666 incr ncleft($p) -1 | |
667 if {![info exists commitinfo($p)]} { | |
668 readcommit $p | |
669 if {![info exists commitinfo($p)]} continue | |
670 } | |
671 lappend actualparents $p | |
672 set ofill blue | |
673 } | |
674 } | |
675 } | |
676 if {![info exists commitinfo($id)]} { | |
677 readcommit $id | |
678 if {![info exists commitinfo($id)]} { | |
679 set commitinfo($id) {"No commit information available"} | |
680 } | |
681 } | |
682 set x [expr $canvx0 + $level * $linespc] | |
683 set y2 [expr $canvy + $linespc] | |
684 if {[info exists linestarty($level)] && $linestarty($level) < $canvy} { | |
685 set t [$canv create line $x $linestarty($level) $x $canvy \ | |
686 -width $lthickness -fill $colormap($id)] | |
687 $canv lower $t | |
688 } | |
689 set linestarty($level) $canvy | |
690 set orad [expr {$linespc / 3}] | |
691 set t [$canv create oval [expr $x - $orad] [expr $canvy - $orad] \ | |
692 [expr $x + $orad - 1] [expr $canvy + $orad - 1] \ | |
693 -fill $ofill -outline black -width 1] | |
694 $canv raise $t | |
695 set xt [expr $canvx0 + $nlines * $linespc] | |
696 if {$nparents($id) > 2} { | |
697 set xt [expr {$xt + ($nparents($id) - 2) * $linespc}] | |
698 } | |
699 if {[info exists idtags($id)] && $idtags($id) != {}} { | |
700 set delta [expr {int(0.5 * ($linespc - $lthickness))}] | |
701 set yt [expr $canvy - 0.5 * $linespc] | |
702 set yb [expr $yt + $linespc - 1] | |
703 set xvals {} | |
704 set wvals {} | |
705 foreach tag $idtags($id) { | |
706 set wid [font measure $mainfont $tag] | |
707 lappend xvals $xt | |
708 lappend wvals $wid | |
709 set xt [expr {$xt + $delta + $wid + $lthickness + $linespc}] | |
710 } | |
711 set t [$canv create line $x $canvy [lindex $xvals end] $canvy \ | |
712 -width $lthickness -fill black] | |
713 $canv lower $t | |
714 foreach tag $idtags($id) x $xvals wid $wvals { | |
715 set xl [expr $x + $delta] | |
716 set xr [expr $x + $delta + $wid + $lthickness] | |
717 $canv create polygon $x [expr $yt + $delta] $xl $yt\ | |
718 $xr $yt $xr $yb $xl $yb $x [expr $yb - $delta] \ | |
719 -width 1 -outline black -fill yellow | |
720 $canv create text $xl $canvy -anchor w -text $tag \ | |
721 -font $mainfont | |
722 } | |
723 } | |
724 set headline [lindex $commitinfo($id) 0] | |
725 set name [lindex $commitinfo($id) 1] | |
726 set date [lindex $commitinfo($id) 2] | |
727 set linehtag($lineno) [$canv create text $xt $canvy -anchor w \ | |
728 -text $headline -font $mainfont ] | |
729 set linentag($lineno) [$canv2 create text 3 $canvy -anchor w \ | |
730 -text $name -font $namefont] | |
731 set linedtag($lineno) [$canv3 create text 3 $canvy -anchor w \ | |
732 -text $date -font $mainfont] | |
733 if {!$datemode && [llength $actualparents] == 1} { | |
734 set p [lindex $actualparents 0] | |
735 if {$ncleft($p) == 0 && [lsearch -exact $todo $p] < 0} { | |
736 assigncolor $p | |
737 set todo [lreplace $todo $level $level $p] | |
738 continue | |
739 } | |
740 } | |
741 | |
742 set oldtodo $todo | |
743 set oldlevel $level | |
744 set lines {} | |
745 for {set i 0} {$i < $nlines} {incr i} { | |
746 if {[lindex $todo $i] == {}} continue | |
747 if {[info exists linestarty($i)]} { | |
748 set oldstarty($i) $linestarty($i) | |
749 unset linestarty($i) | |
750 } | |
751 if {$i != $level} { | |
752 lappend lines [list $i [lindex $todo $i]] | |
753 } | |
754 } | |
755 if {$nullentry >= 0} { | |
756 set todo [lreplace $todo $nullentry $nullentry] | |
757 if {$nullentry < $level} { | |
758 incr level -1 | |
759 } | |
760 } | |
761 | |
762 set todo [lreplace $todo $level $level] | |
763 if {$nullentry > $level} { | |
764 incr nullentry -1 | |
765 } | |
766 set i $level | |
767 foreach p $actualparents { | |
768 set k [lsearch -exact $todo $p] | |
769 if {$k < 0} { | |
770 assigncolor $p | |
771 set todo [linsert $todo $i $p] | |
772 if {$nullentry >= $i} { | |
773 incr nullentry | |
774 } | |
775 incr i | |
776 } | |
777 lappend lines [list $oldlevel $p] | |
778 } | |
779 | |
780 # choose which one to do next time around | |
781 set todol [llength $todo] | |
782 set level -1 | |
783 set latest {} | |
784 for {set k $todol} {[incr k -1] >= 0} {} { | |
785 set p [lindex $todo $k] | |
786 if {$p == {}} continue | |
787 if {$ncleft($p) == 0} { | |
788 if {$datemode} { | |
789 if {$latest == {} || $cdate($p) > $latest} { | |
790 set level $k | |
791 set latest $cdate($p) | |
792 } | |
793 } else { | |
794 set level $k | |
795 break | |
796 } | |
797 } | |
798 } | |
799 if {$level < 0} { | |
800 if {$todo != {}} { | |
801 puts "ERROR: none of the pending commits can be done yet:" | |
802 foreach p $todo { | |
803 puts " $p" | |
804 } | |
805 } | |
806 break | |
807 } | |
808 | |
809 # If we are reducing, put in a null entry | |
810 if {$todol < $nlines} { | |
811 if {$nullentry >= 0} { | |
812 set i $nullentry | |
813 while {$i < $todol | |
814 && [lindex $oldtodo $i] == [lindex $todo $i]} { | |
815 incr i | |
816 } | |
817 } else { | |
818 set i $oldlevel | |
819 if {$level >= $i} { | |
820 incr i | |
821 } | |
822 } | |
823 if {$i >= $todol} { | |
824 set nullentry -1 | |
825 } else { | |
826 set nullentry $i | |
827 set todo [linsert $todo $nullentry {}] | |
828 if {$level >= $i} { | |
829 incr level | |
830 } | |
831 } | |
832 } else { | |
833 set nullentry -1 | |
834 } | |
835 | |
836 foreach l $lines { | |
837 set i [lindex $l 0] | |
838 set dst [lindex $l 1] | |
839 set j [lsearch -exact $todo $dst] | |
840 if {$i == $j} { | |
841 if {[info exists oldstarty($i)]} { | |
842 set linestarty($i) $oldstarty($i) | |
843 } | |
844 continue | |
845 } | |
846 set xi [expr {$canvx0 + $i * $linespc}] | |
847 set xj [expr {$canvx0 + $j * $linespc}] | |
848 set coords {} | |
849 if {[info exists oldstarty($i)] && $oldstarty($i) < $canvy} { | |
850 lappend coords $xi $oldstarty($i) | |
851 } | |
852 lappend coords $xi $canvy | |
853 if {$j < $i - 1} { | |
854 lappend coords [expr $xj + $linespc] $canvy | |
855 } elseif {$j > $i + 1} { | |
856 lappend coords [expr $xj - $linespc] $canvy | |
857 } | |
858 lappend coords $xj $y2 | |
859 set t [$canv create line $coords -width $lthickness \ | |
860 -fill $colormap($dst)] | |
861 $canv lower $t | |
862 if {![info exists linestarty($j)]} { | |
863 set linestarty($j) $y2 | |
864 } | |
865 } | |
866 } | |
867 set phase {} | |
868 if {$redisplaying} { | |
869 if {$stopped == 0 && [info exists selectedline]} { | |
870 selectline $selectedline | |
871 } | |
872 if {$stopped == 1} { | |
873 set stopped 0 | |
874 after idle drawgraph | |
875 } else { | |
876 set redisplaying 0 | |
877 } | |
878 } | |
879 } | |
880 | |
881 proc findmatches {f} { | |
882 global findtype foundstring foundstrlen | |
883 if {$findtype == "Regexp"} { | |
884 set matches [regexp -indices -all -inline $foundstring $f] | |
885 } else { | |
886 if {$findtype == "IgnCase"} { | |
887 set str [string tolower $f] | |
888 } else { | |
889 set str $f | |
890 } | |
891 set matches {} | |
892 set i 0 | |
893 while {[set j [string first $foundstring $str $i]] >= 0} { | |
894 lappend matches [list $j [expr $j+$foundstrlen-1]] | |
895 set i [expr $j + $foundstrlen] | |
896 } | |
897 } | |
898 return $matches | |
899 } | |
900 | |
901 proc dofind {} { | |
902 global findtype findloc findstring markedmatches commitinfo | |
903 global numcommits lineid linehtag linentag linedtag | |
904 global mainfont namefont canv canv2 canv3 selectedline | |
905 global matchinglines foundstring foundstrlen idtags | |
906 unmarkmatches | |
907 focus . | |
908 set matchinglines {} | |
909 set fldtypes {Headline Author Date Committer CDate Comment} | |
910 if {$findtype == "IgnCase"} { | |
911 set foundstring [string tolower $findstring] | |
912 } else { | |
913 set foundstring $findstring | |
914 } | |
915 set foundstrlen [string length $findstring] | |
916 if {$foundstrlen == 0} return | |
917 if {![info exists selectedline]} { | |
918 set oldsel -1 | |
919 } else { | |
920 set oldsel $selectedline | |
921 } | |
922 set didsel 0 | |
923 for {set l 0} {$l < $numcommits} {incr l} { | |
924 set id $lineid($l) | |
925 set info $commitinfo($id) | |
926 set doesmatch 0 | |
927 foreach f $info ty $fldtypes { | |
928 if {$findloc != "All fields" && $findloc != $ty} { | |
929 continue | |
930 } | |
931 set matches [findmatches $f] | |
932 if {$matches == {}} continue | |
933 set doesmatch 1 | |
934 if {$ty == "Headline"} { | |
935 markmatches $canv $l $f $linehtag($l) $matches $mainfont | |
936 } elseif {$ty == "Author"} { | |
937 markmatches $canv2 $l $f $linentag($l) $matches $namefont | |
938 } elseif {$ty == "Date"} { | |
939 markmatches $canv3 $l $f $linedtag($l) $matches $mainfont | |
940 } | |
941 } | |
942 if {$doesmatch} { | |
943 lappend matchinglines $l | |
944 if {!$didsel && $l > $oldsel} { | |
945 findselectline $l | |
946 set didsel 1 | |
947 } | |
948 } | |
949 } | |
950 if {$matchinglines == {}} { | |
951 bell | |
952 } elseif {!$didsel} { | |
953 findselectline [lindex $matchinglines 0] | |
954 } | |
955 } | |
956 | |
957 proc findselectline {l} { | |
958 global findloc commentend ctext | |
959 selectline $l | |
960 if {$findloc == "All fields" || $findloc == "Comments"} { | |
961 # highlight the matches in the comments | |
962 set f [$ctext get 1.0 $commentend] | |
963 set matches [findmatches $f] | |
964 foreach match $matches { | |
965 set start [lindex $match 0] | |
966 set end [expr [lindex $match 1] + 1] | |
967 $ctext tag add found "1.0 + $start c" "1.0 + $end c" | |
968 } | |
969 } | |
970 } | |
971 | |
972 proc findnext {} { | |
973 global matchinglines selectedline | |
974 if {![info exists matchinglines]} { | |
975 dofind | |
976 return | |
977 } | |
978 if {![info exists selectedline]} return | |
979 foreach l $matchinglines { | |
980 if {$l > $selectedline} { | |
981 findselectline $l | |
982 return | |
983 } | |
984 } | |
985 bell | |
986 } | |
987 | |
988 proc findprev {} { | |
989 global matchinglines selectedline | |
990 if {![info exists matchinglines]} { | |
991 dofind | |
992 return | |
993 } | |
994 if {![info exists selectedline]} return | |
995 set prev {} | |
996 foreach l $matchinglines { | |
997 if {$l >= $selectedline} break | |
998 set prev $l | |
999 } | |
1000 if {$prev != {}} { | |
1001 findselectline $prev | |
1002 } else { | |
1003 bell | |
1004 } | |
1005 } | |
1006 | |
1007 proc markmatches {canv l str tag matches font} { | |
1008 set bbox [$canv bbox $tag] | |
1009 set x0 [lindex $bbox 0] | |
1010 set y0 [lindex $bbox 1] | |
1011 set y1 [lindex $bbox 3] | |
1012 foreach match $matches { | |
1013 set start [lindex $match 0] | |
1014 set end [lindex $match 1] | |
1015 if {$start > $end} continue | |
1016 set xoff [font measure $font [string range $str 0 [expr $start-1]]] | |
1017 set xlen [font measure $font [string range $str 0 [expr $end]]] | |
1018 set t [$canv create rect [expr $x0+$xoff] $y0 [expr $x0+$xlen+2] $y1 \ | |
1019 -outline {} -tags matches -fill yellow] | |
1020 $canv lower $t | |
1021 } | |
1022 } | |
1023 | |
1024 proc unmarkmatches {} { | |
1025 global matchinglines | |
1026 allcanvs delete matches | |
1027 catch {unset matchinglines} | |
1028 } | |
1029 | |
1030 proc selcanvline {x y} { | |
1031 global canv canvy0 ctext linespc selectedline | |
1032 global lineid linehtag linentag linedtag | |
1033 set ymax [lindex [$canv cget -scrollregion] 3] | |
1034 if {$ymax == {}} return | |
1035 set yfrac [lindex [$canv yview] 0] | |
1036 set y [expr {$y + $yfrac * $ymax}] | |
1037 set l [expr {int(($y - $canvy0) / $linespc + 0.5)}] | |
1038 if {$l < 0} { | |
1039 set l 0 | |
1040 } | |
1041 if {[info exists selectedline] && $selectedline == $l} return | |
1042 unmarkmatches | |
1043 selectline $l | |
1044 } | |
1045 | |
1046 proc selectline {l} { | |
1047 global canv canv2 canv3 ctext commitinfo selectedline | |
1048 global lineid linehtag linentag linedtag | |
1049 global canvy0 linespc nparents treepending | |
1050 global cflist treediffs currentid sha1entry | |
1051 global commentend seenfile numcommits idtags | |
1052 if {![info exists lineid($l)] || ![info exists linehtag($l)]} return | |
1053 $canv delete secsel | |
1054 set t [eval $canv create rect [$canv bbox $linehtag($l)] -outline {{}} \ | |
1055 -tags secsel -fill [$canv cget -selectbackground]] | |
1056 $canv lower $t | |
1057 $canv2 delete secsel | |
1058 set t [eval $canv2 create rect [$canv2 bbox $linentag($l)] -outline {{}} \ | |
1059 -tags secsel -fill [$canv2 cget -selectbackground]] | |
1060 $canv2 lower $t | |
1061 $canv3 delete secsel | |
1062 set t [eval $canv3 create rect [$canv3 bbox $linedtag($l)] -outline {{}} \ | |
1063 -tags secsel -fill [$canv3 cget -selectbackground]] | |
1064 $canv3 lower $t | |
1065 set y [expr {$canvy0 + $l * $linespc}] | |
1066 set ymax [lindex [$canv cget -scrollregion] 3] | |
1067 set ytop [expr {$y - $linespc - 1}] | |
1068 set ybot [expr {$y + $linespc + 1}] | |
1069 set wnow [$canv yview] | |
1070 set wtop [expr [lindex $wnow 0] * $ymax] | |
1071 set wbot [expr [lindex $wnow 1] * $ymax] | |
1072 set wh [expr {$wbot - $wtop}] | |
1073 set newtop $wtop | |
1074 if {$ytop < $wtop} { | |
1075 if {$ybot < $wtop} { | |
1076 set newtop [expr {$y - $wh / 2.0}] | |
1077 } else { | |
1078 set newtop $ytop | |
1079 if {$newtop > $wtop - $linespc} { | |
1080 set newtop [expr {$wtop - $linespc}] | |
1081 } | |
1082 } | |
1083 } elseif {$ybot > $wbot} { | |
1084 if {$ytop > $wbot} { | |
1085 set newtop [expr {$y - $wh / 2.0}] | |
1086 } else { | |
1087 set newtop [expr {$ybot - $wh}] | |
1088 if {$newtop < $wtop + $linespc} { | |
1089 set newtop [expr {$wtop + $linespc}] | |
1090 } | |
1091 } | |
1092 } | |
1093 if {$newtop != $wtop} { | |
1094 if {$newtop < 0} { | |
1095 set newtop 0 | |
1096 } | |
1097 allcanvs yview moveto [expr $newtop * 1.0 / $ymax] | |
1098 } | |
1099 set selectedline $l | |
1100 | |
1101 set id $lineid($l) | |
1102 set currentid $id | |
1103 $sha1entry delete 0 end | |
1104 $sha1entry insert 0 $id | |
1105 $sha1entry selection from 0 | |
1106 $sha1entry selection to end | |
1107 | |
1108 $ctext conf -state normal | |
1109 $ctext delete 0.0 end | |
1110 set info $commitinfo($id) | |
1111 $ctext insert end "Author: [lindex $info 1] [lindex $info 2]\n" | |
1112 $ctext insert end "Committer: [lindex $info 3] [lindex $info 4]\n" | |
1113 if {[info exists idtags($id)]} { | |
1114 $ctext insert end "Tags:" | |
1115 foreach tag $idtags($id) { | |
1116 $ctext insert end " $tag" | |
1117 } | |
1118 $ctext insert end "\n" | |
1119 } | |
1120 $ctext insert end "\n" | |
1121 $ctext insert end [lindex $info 5] | |
1122 $ctext insert end "\n" | |
1123 $ctext tag delete Comments | |
1124 $ctext tag remove found 1.0 end | |
1125 $ctext conf -state disabled | |
1126 set commentend [$ctext index "end - 1c"] | |
1127 | |
1128 $cflist delete 0 end | |
1129 if {$nparents($id) == 1} { | |
1130 if {![info exists treediffs($id)]} { | |
1131 if {![info exists treepending]} { | |
1132 gettreediffs $id | |
1133 } | |
1134 } else { | |
1135 addtocflist $id | |
1136 } | |
1137 } | |
1138 catch {unset seenfile} | |
1139 } | |
1140 | |
1141 proc selnextline {dir} { | |
1142 global selectedline | |
1143 if {![info exists selectedline]} return | |
1144 set l [expr $selectedline + $dir] | |
1145 unmarkmatches | |
1146 selectline $l | |
1147 } | |
1148 | |
1149 proc addtocflist {id} { | |
1150 global currentid treediffs cflist treepending | |
1151 if {$id != $currentid} { | |
1152 gettreediffs $currentid | |
1153 return | |
1154 } | |
1155 $cflist insert end "All files" | |
1156 foreach f $treediffs($currentid) { | |
1157 $cflist insert end $f | |
1158 } | |
1159 getblobdiffs $id | |
1160 } | |
1161 | |
1162 proc gettreediffs {id} { | |
1163 global treediffs parents treepending | |
1164 set treepending $id | |
1165 set treediffs($id) {} | |
1166 set p [lindex $parents($id) 0] | |
1167 puts stderr "hgit diff-tree -r $p $id" | |
1168 if [catch {set gdtf [open "|hgit diff-tree -r $p $id" r]}] return | |
1169 fconfigure $gdtf -blocking 0 | |
1170 fileevent $gdtf readable "gettreediffline $gdtf $id" | |
1171 } | |
1172 | |
1173 proc gettreediffline {gdtf id} { | |
1174 global treediffs treepending | |
1175 set n [gets $gdtf line] | |
1176 if {$n < 0} { | |
1177 if {![eof $gdtf]} return | |
1178 close $gdtf | |
1179 unset treepending | |
1180 addtocflist $id | |
1181 return | |
1182 } | |
1183 set file [lindex $line 5] | |
1184 lappend treediffs($id) $file | |
1185 } | |
1186 | |
1187 proc getblobdiffs {id} { | |
1188 global parents diffopts blobdifffd env curdifftag curtagstart | |
1189 global diffindex difffilestart | |
1190 set p [lindex $parents($id) 0] | |
1191 set env(GIT_DIFF_OPTS) $diffopts | |
1192 if [catch {set bdf [open "|hgit diff-tree -r -p $p $id" r]} err] { | |
1193 puts "error getting diffs: $err" | |
1194 return | |
1195 } | |
1196 fconfigure $bdf -blocking 0 | |
1197 set blobdifffd($id) $bdf | |
1198 set curdifftag Comments | |
1199 set curtagstart 0.0 | |
1200 set diffindex 0 | |
1201 catch {unset difffilestart} | |
1202 fileevent $bdf readable "getblobdiffline $bdf $id" | |
1203 } | |
1204 | |
1205 proc getblobdiffline {bdf id} { | |
1206 global currentid blobdifffd ctext curdifftag curtagstart seenfile | |
1207 global diffnexthead diffnextnote diffindex difffilestart | |
1208 set n [gets $bdf line] | |
1209 if {$n < 0} { | |
1210 if {[eof $bdf]} { | |
1211 close $bdf | |
1212 if {$id == $currentid && $bdf == $blobdifffd($id)} { | |
1213 $ctext tag add $curdifftag $curtagstart end | |
1214 set seenfile($curdifftag) 1 | |
1215 } | |
1216 } | |
1217 return | |
1218 } | |
1219 if {$id != $currentid || $bdf != $blobdifffd($id)} { | |
1220 return | |
1221 } | |
1222 $ctext conf -state normal | |
274
5da941efbb52
[PATCH] hgk should parse dates in the diff output
mpm@selenic.com
parents:
267
diff
changeset
|
1223 if {[regexp {^---[ \t]+([^/])*/([^\t]*)} $line match s0 fname]} { |
267 | 1224 # start of a new file |
1225 $ctext insert end "\n" | |
1226 $ctext tag add $curdifftag $curtagstart end | |
1227 set seenfile($curdifftag) 1 | |
1228 set curtagstart [$ctext index "end - 1c"] | |
1229 set header $fname | |
1230 if {[info exists diffnexthead]} { | |
1231 set fname $diffnexthead | |
1232 set header "$diffnexthead ($diffnextnote)" | |
1233 unset diffnexthead | |
1234 } | |
1235 set difffilestart($diffindex) [$ctext index "end - 1c"] | |
1236 incr diffindex | |
1237 set curdifftag "f:$fname" | |
1238 $ctext tag delete $curdifftag | |
1239 set l [expr {(78 - [string length $header]) / 2}] | |
1240 set pad [string range "----------------------------------------" 1 $l] | |
1241 $ctext insert end "$pad $header $pad\n" filesep | |
1242 } elseif {[string range $line 0 2] == "+++"} { | |
1243 # no need to do anything with this | |
1244 } elseif {[regexp {^Created: (.*) \((mode: *[0-7]*)\)} $line match fn m]} { | |
1245 set diffnexthead $fn | |
1246 set diffnextnote "created, mode $m" | |
1247 } elseif {[string range $line 0 8] == "Deleted: "} { | |
1248 set diffnexthead [string range $line 9 end] | |
1249 set diffnextnote "deleted" | |
1250 } elseif {[regexp {^diff --git a/(.*) b/} $line match fn]} { | |
1251 # save the filename in case the next thing is "new file mode ..." | |
1252 set diffnexthead $fn | |
1253 set diffnextnote "modified" | |
1254 } elseif {[regexp {^new file mode ([0-7]+)} $line match m]} { | |
1255 set diffnextnote "new file, mode $m" | |
1256 } elseif {[string range $line 0 11] == "deleted file"} { | |
1257 set diffnextnote "deleted" | |
1258 } elseif {[regexp {^@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@(.*)} \ | |
1259 $line match f1l f1c f2l f2c rest]} { | |
1260 $ctext insert end "\t" hunksep | |
1261 $ctext insert end " $f1l " d0 " $f2l " d1 | |
1262 $ctext insert end " $rest \n" hunksep | |
1263 } else { | |
1264 set x [string range $line 0 0] | |
1265 if {$x == "-" || $x == "+"} { | |
1266 set tag [expr {$x == "+"}] | |
1267 set line [string range $line 1 end] | |
1268 $ctext insert end "$line\n" d$tag | |
1269 } elseif {$x == " "} { | |
1270 set line [string range $line 1 end] | |
1271 $ctext insert end "$line\n" | |
1272 } elseif {$x == "\\"} { | |
1273 # e.g. "\ No newline at end of file" | |
1274 $ctext insert end "$line\n" filesep | |
1275 } else { | |
1276 # Something else we don't recognize | |
1277 if {$curdifftag != "Comments"} { | |
1278 $ctext insert end "\n" | |
1279 $ctext tag add $curdifftag $curtagstart end | |
1280 set seenfile($curdifftag) 1 | |
1281 set curtagstart [$ctext index "end - 1c"] | |
1282 set curdifftag Comments | |
1283 } | |
1284 $ctext insert end "$line\n" filesep | |
1285 } | |
1286 } | |
1287 $ctext conf -state disabled | |
1288 } | |
1289 | |
1290 proc nextfile {} { | |
1291 global difffilestart ctext | |
1292 set here [$ctext index @0,0] | |
1293 for {set i 0} {[info exists difffilestart($i)]} {incr i} { | |
1294 if {[$ctext compare $difffilestart($i) > $here]} { | |
1295 $ctext yview $difffilestart($i) | |
1296 break | |
1297 } | |
1298 } | |
1299 } | |
1300 | |
1301 proc listboxsel {} { | |
1302 global ctext cflist currentid treediffs seenfile | |
1303 if {![info exists currentid]} return | |
1304 set sel [$cflist curselection] | |
1305 if {$sel == {} || [lsearch -exact $sel 0] >= 0} { | |
1306 # show everything | |
1307 $ctext tag conf Comments -elide 0 | |
1308 foreach f $treediffs($currentid) { | |
1309 if [info exists seenfile(f:$f)] { | |
1310 $ctext tag conf "f:$f" -elide 0 | |
1311 } | |
1312 } | |
1313 } else { | |
1314 # just show selected files | |
1315 $ctext tag conf Comments -elide 1 | |
1316 set i 1 | |
1317 foreach f $treediffs($currentid) { | |
1318 set elide [expr {[lsearch -exact $sel $i] < 0}] | |
1319 if [info exists seenfile(f:$f)] { | |
1320 $ctext tag conf "f:$f" -elide $elide | |
1321 } | |
1322 incr i | |
1323 } | |
1324 } | |
1325 } | |
1326 | |
1327 proc setcoords {} { | |
1328 global linespc charspc canvx0 canvy0 mainfont | |
1329 set linespc [font metrics $mainfont -linespace] | |
1330 set charspc [font measure $mainfont "m"] | |
1331 set canvy0 [expr 3 + 0.5 * $linespc] | |
1332 set canvx0 [expr 3 + 0.5 * $linespc] | |
1333 } | |
1334 | |
1335 proc redisplay {} { | |
1336 global selectedline stopped redisplaying phase | |
1337 if {$stopped > 1} return | |
1338 if {$phase == "getcommits"} return | |
1339 set redisplaying 1 | |
1340 if {$phase == "drawgraph"} { | |
1341 set stopped 1 | |
1342 } else { | |
1343 drawgraph | |
1344 } | |
1345 } | |
1346 | |
1347 proc incrfont {inc} { | |
1348 global mainfont namefont textfont selectedline ctext canv phase | |
1349 global stopped entries | |
1350 unmarkmatches | |
1351 set mainfont [lreplace $mainfont 1 1 [expr {[lindex $mainfont 1] + $inc}]] | |
1352 set namefont [lreplace $namefont 1 1 [expr {[lindex $namefont 1] + $inc}]] | |
1353 set textfont [lreplace $textfont 1 1 [expr {[lindex $textfont 1] + $inc}]] | |
1354 setcoords | |
1355 $ctext conf -font $textfont | |
1356 $ctext tag conf filesep -font [concat $textfont bold] | |
1357 foreach e $entries { | |
1358 $e conf -font $mainfont | |
1359 } | |
1360 if {$phase == "getcommits"} { | |
1361 $canv itemconf textitems -font $mainfont | |
1362 } | |
1363 redisplay | |
1364 } | |
1365 | |
1366 proc sha1change {n1 n2 op} { | |
1367 global sha1string currentid sha1but | |
1368 if {$sha1string == {} | |
1369 || ([info exists currentid] && $sha1string == $currentid)} { | |
1370 set state disabled | |
1371 } else { | |
1372 set state normal | |
1373 } | |
1374 if {[$sha1but cget -state] == $state} return | |
1375 if {$state == "normal"} { | |
1376 $sha1but conf -state normal -relief raised -text "Goto: " | |
1377 } else { | |
1378 $sha1but conf -state disabled -relief flat -text "SHA1 ID: " | |
1379 } | |
1380 } | |
1381 | |
1382 proc gotocommit {} { | |
1383 global sha1string currentid idline tagids | |
1384 if {$sha1string == {} | |
1385 || ([info exists currentid] && $sha1string == $currentid)} return | |
1386 if {[info exists tagids($sha1string)]} { | |
1387 set id $tagids($sha1string) | |
1388 } else { | |
1389 set id [string tolower $sha1string] | |
1390 } | |
1391 if {[info exists idline($id)]} { | |
1392 selectline $idline($id) | |
1393 return | |
1394 } | |
1395 if {[regexp {^[0-9a-fA-F]{40}$} $sha1string]} { | |
1396 set type "SHA1 id" | |
1397 } else { | |
1398 set type "Tag" | |
1399 } | |
1400 error_popup "$type $sha1string is not known" | |
1401 } | |
1402 | |
1403 proc doquit {} { | |
1404 global stopped | |
1405 set stopped 100 | |
1406 destroy . | |
1407 } | |
1408 | |
1409 # defaults... | |
1410 set datemode 0 | |
1411 set boldnames 0 | |
1412 set diffopts "-U 5 -p" | |
1413 | |
1414 set mainfont {Helvetica 9} | |
1415 set textfont {Courier 9} | |
1416 | |
1417 set colors {green red blue magenta darkgrey brown orange} | |
1418 set colorbycommitter false | |
1419 | |
1420 catch {source ~/.gitk} | |
1421 | |
1422 set namefont $mainfont | |
1423 if {$boldnames} { | |
1424 lappend namefont bold | |
1425 } | |
1426 | |
1427 set revtreeargs {} | |
1428 foreach arg $argv { | |
1429 switch -regexp -- $arg { | |
1430 "^$" { } | |
1431 "^-b" { set boldnames 1 } | |
1432 "^-c" { set colorbycommitter 1 } | |
1433 "^-d" { set datemode 1 } | |
1434 default { | |
1435 lappend revtreeargs $arg | |
1436 } | |
1437 } | |
1438 } | |
1439 | |
1440 set stopped 0 | |
1441 set redisplaying 0 | |
1442 set stuffsaved 0 | |
1443 setcoords | |
1444 makewindow | |
1445 readrefs | |
1446 readfullcommits $revtreeargs |