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