]> git.ipfire.org Git - thirdparty/git.git/blame - gitk
cope with changed git-diff-tree output format
[thirdparty/git.git] / gitk
CommitLineData
1db95b00
PM
1#!/bin/sh
2# Tcl ignores the next line -*- tcl -*- \
3exec wish "$0" -- "${1+$@}"
4
5# Copyright (C) 2005 Paul Mackerras. All rights reserved.
6# This program is free software; it may be used, copied, modified
7# and distributed under the terms of the GNU General Public Licence,
8# either version 2, or (at your option) any later version.
9
d4e95cb6 10# CVS $Revision: 1.20 $
1db95b00
PM
11
12proc getcommits {rargs} {
1d10f36d 13 global commits commfd phase canv mainfont
1db95b00
PM
14 if {$rargs == {}} {
15 set rargs HEAD
16 }
17 set commits {}
1d10f36d 18 set phase getcommits
cfb4563c
PM
19 if [catch {set commfd [open "|git-rev-list $rargs" r]} err] {
20 puts stderr "Error executing git-rev-list: $err"
1d10f36d
PM
21 exit 1
22 }
23 fconfigure $commfd -blocking 0
24 fileevent $commfd readable "getcommitline $commfd"
25 $canv delete all
26 $canv create text 3 3 -anchor nw -text "Reading commits..." \
27 -font $mainfont -tags textitems
28}
29
30proc getcommitline {commfd} {
31 global commits parents cdate nparents children nchildren
32 set n [gets $commfd line]
33 if {$n < 0} {
34 if {![eof $commfd]} return
df3d83b1
PM
35 # this works around what is apparently a bug in Tcl...
36 fconfigure $commfd -blocking 1
1d10f36d 37 if {![catch {close $commfd} err]} {
cfb4563c 38 after idle readallcommits
1d10f36d
PM
39 return
40 }
9a40c50c 41 if {[string range $err 0 4] == "usage"} {
df3d83b1 42 set err "\
cfb4563c
PM
43Gitk: error reading commits: bad arguments to git-rev-list.\n\
44(Note: arguments to gitk are passed to git-rev-list\
df3d83b1 45to allow selection of commits to be displayed.)"
9a40c50c 46 } else {
df3d83b1 47 set err "Error reading commits: $err"
9a40c50c 48 }
df3d83b1 49 error_popup $err
1d10f36d 50 exit 1
9a40c50c 51 }
cfb4563c
PM
52 if {![regexp {^[0-9a-f]{40}$} $line]} {
53 error_popup "Can't parse git-rev-tree output: {$line}"
54 exit 1
55 }
56 lappend commits $line
57}
1d10f36d 58
cfb4563c
PM
59proc readallcommits {} {
60 global commits
61 foreach id $commits {
62 readcommit $id
63 update
1db95b00 64 }
cfb4563c 65 drawgraph
1db95b00
PM
66}
67
68proc readcommit {id} {
cfb4563c 69 global commitinfo children nchildren parents nparents cdate
1db95b00
PM
70 set inhdr 1
71 set comment {}
72 set headline {}
73 set auname {}
74 set audate {}
75 set comname {}
76 set comdate {}
cfb4563c
PM
77 if {![info exists nchildren($id)]} {
78 set children($id) {}
79 set nchildren($id) 0
80 }
81 set parents($id) {}
82 set nparents($id) 0
df3d83b1
PM
83 if [catch {set contents [exec git-cat-file commit $id]}] return
84 foreach line [split $contents "\n"] {
1db95b00
PM
85 if {$inhdr} {
86 if {$line == {}} {
87 set inhdr 0
88 } else {
89 set tag [lindex $line 0]
cfb4563c
PM
90 if {$tag == "parent"} {
91 set p [lindex $line 1]
92 if {![info exists nchildren($p)]} {
93 set children($p) {}
94 set nchildren($p) 0
95 }
96 lappend parents($id) $p
97 incr nparents($id)
98 if {[lsearch -exact $children($p) $id] < 0} {
99 lappend children($p) $id
100 incr nchildren($p)
101 }
102 } elseif {$tag == "author"} {
1db95b00
PM
103 set x [expr {[llength $line] - 2}]
104 set audate [lindex $line $x]
105 set auname [lrange $line 1 [expr {$x - 1}]]
106 } elseif {$tag == "committer"} {
107 set x [expr {[llength $line] - 2}]
108 set comdate [lindex $line $x]
109 set comname [lrange $line 1 [expr {$x - 1}]]
110 }
111 }
112 } else {
113 if {$comment == {}} {
114 set headline $line
115 } else {
116 append comment "\n"
117 }
118 append comment $line
119 }
120 }
121 if {$audate != {}} {
122 set audate [clock format $audate -format "%Y-%m-%d %H:%M:%S"]
123 }
124 if {$comdate != {}} {
cfb4563c 125 set cdate($id) $comdate
1db95b00
PM
126 set comdate [clock format $comdate -format "%Y-%m-%d %H:%M:%S"]
127 }
e5c2d856
PM
128 set commitinfo($id) [list $headline $auname $audate \
129 $comname $comdate $comment]
1db95b00
PM
130}
131
887fe3c4
PM
132proc readrefs {} {
133 global tagids idtags
134 set tags [glob -nocomplain -types f .git/refs/tags/*]
135 foreach f $tags {
136 catch {
137 set fd [open $f r]
138 set line [read $fd]
139 if {[regexp {^[0-9a-f]{40}} $line id]} {
140 set contents [split [exec git-cat-file tag $id] "\n"]
141 set obj {}
142 set type {}
143 set tag {}
144 foreach l $contents {
145 if {$l == {}} break
146 switch -- [lindex $l 0] {
147 "object" {set obj [lindex $l 1]}
148 "type" {set type [lindex $l 1]}
149 "tag" {set tag [string range $l 4 end]}
150 }
151 }
152 if {$obj != {} && $type == "commit" && $tag != {}} {
153 set tagids($tag) $obj
154 lappend idtags($obj) $tag
155 }
156 }
157 }
158 }
159}
160
df3d83b1
PM
161proc error_popup msg {
162 set w .error
163 toplevel $w
164 wm transient $w .
165 message $w.m -text $msg -justify center -aspect 400
166 pack $w.m -side top -fill x -padx 20 -pady 20
167 button $w.ok -text OK -command "destroy $w"
168 pack $w.ok -side bottom -fill x
169 bind $w <Visibility> "grab $w; focus $w"
170 tkwait window $w
171}
172
1db95b00 173proc makewindow {} {
e5c2d856 174 global canv canv2 canv3 linespc charspc ctext cflist textfont
887fe3c4
PM
175 global findtype findloc findstring fstring geometry
176 global entries sha1entry sha1string sha1but
9a40c50c
PM
177
178 menu .bar
179 .bar add cascade -label "File" -menu .bar.file
180 menu .bar.file
1d10f36d 181 .bar.file add command -label "Quit" -command doquit
9a40c50c
PM
182 menu .bar.help
183 .bar add cascade -label "Help" -menu .bar.help
184 .bar.help add command -label "About gitk" -command about
185 . configure -menu .bar
186
0fba86b3
PM
187 if {![info exists geometry(canv1)]} {
188 set geometry(canv1) [expr 45 * $charspc]
189 set geometry(canv2) [expr 30 * $charspc]
190 set geometry(canv3) [expr 15 * $charspc]
191 set geometry(canvh) [expr 25 * $linespc + 4]
192 set geometry(ctextw) 80
193 set geometry(ctexth) 30
194 set geometry(cflistw) 30
195 }
0327d27a 196 panedwindow .ctop -orient vertical
0fba86b3
PM
197 if {[info exists geometry(width)]} {
198 .ctop conf -width $geometry(width) -height $geometry(height)
17386066
PM
199 set texth [expr {$geometry(height) - $geometry(canvh) - 56}]
200 set geometry(ctexth) [expr {($texth - 8) /
201 [font metrics $textfont -linespace]}]
0fba86b3 202 }
98f350e5
PM
203 frame .ctop.top
204 frame .ctop.top.bar
205 pack .ctop.top.bar -side bottom -fill x
206 set cscroll .ctop.top.csb
207 scrollbar $cscroll -command {allcanvs yview} -highlightthickness 0
208 pack $cscroll -side right -fill y
209 panedwindow .ctop.top.clist -orient horizontal -sashpad 0 -handlesize 4
210 pack .ctop.top.clist -side top -fill both -expand 1
211 .ctop add .ctop.top
212 set canv .ctop.top.clist.canv
0fba86b3 213 canvas $canv -height $geometry(canvh) -width $geometry(canv1) \
b5721c72
PM
214 -bg white -bd 0 \
215 -yscrollincr $linespc -yscrollcommand "$cscroll set"
98f350e5
PM
216 .ctop.top.clist add $canv
217 set canv2 .ctop.top.clist.canv2
0fba86b3 218 canvas $canv2 -height $geometry(canvh) -width $geometry(canv2) \
b5721c72 219 -bg white -bd 0 -yscrollincr $linespc
98f350e5
PM
220 .ctop.top.clist add $canv2
221 set canv3 .ctop.top.clist.canv3
0fba86b3 222 canvas $canv3 -height $geometry(canvh) -width $geometry(canv3) \
b5721c72 223 -bg white -bd 0 -yscrollincr $linespc
98f350e5 224 .ctop.top.clist add $canv3
43bddeb4 225 bind .ctop.top.clist <Configure> {resizeclistpanes %W %w}
98f350e5
PM
226
227 set sha1entry .ctop.top.bar.sha1
887fe3c4
PM
228 set entries $sha1entry
229 set sha1but .ctop.top.bar.sha1label
230 button $sha1but -text "SHA1 ID: " -state disabled -relief flat \
231 -command gotocommit -width 8
232 $sha1but conf -disabledforeground [$sha1but cget -foreground]
98f350e5 233 pack .ctop.top.bar.sha1label -side left
887fe3c4
PM
234 entry $sha1entry -width 40 -font $textfont -textvariable sha1string
235 trace add variable sha1string write sha1change
98f350e5
PM
236 pack $sha1entry -side left -pady 2
237 button .ctop.top.bar.findbut -text "Find" -command dofind
238 pack .ctop.top.bar.findbut -side left
239 set findstring {}
df3d83b1 240 set fstring .ctop.top.bar.findstring
887fe3c4 241 lappend entries $fstring
df3d83b1 242 entry $fstring -width 30 -font $textfont -textvariable findstring
df3d83b1 243 pack $fstring -side left -expand 1 -fill x
98f350e5
PM
244 set findtype Exact
245 tk_optionMenu .ctop.top.bar.findtype findtype Exact IgnCase Regexp
246 set findloc "All fields"
247 tk_optionMenu .ctop.top.bar.findloc findloc "All fields" Headline \
248 Comments Author Committer
249 pack .ctop.top.bar.findloc -side right
250 pack .ctop.top.bar.findtype -side right
b5721c72 251
5ad588de
PM
252 panedwindow .ctop.cdet -orient horizontal
253 .ctop add .ctop.cdet
d2610d11
PM
254 frame .ctop.cdet.left
255 set ctext .ctop.cdet.left.ctext
0fba86b3
PM
256 text $ctext -bg white -state disabled -font $textfont \
257 -width $geometry(ctextw) -height $geometry(ctexth) \
d2610d11
PM
258 -yscrollcommand ".ctop.cdet.left.sb set"
259 scrollbar .ctop.cdet.left.sb -command "$ctext yview"
260 pack .ctop.cdet.left.sb -side right -fill y
261 pack $ctext -side left -fill both -expand 1
262 .ctop.cdet add .ctop.cdet.left
263
e5c2d856
PM
264 $ctext tag conf filesep -font [concat $textfont bold]
265 $ctext tag conf hunksep -back blue -fore white
266 $ctext tag conf d0 -back "#ff8080"
267 $ctext tag conf d1 -back green
df3d83b1 268 $ctext tag conf found -back yellow
e5c2d856 269
d2610d11
PM
270 frame .ctop.cdet.right
271 set cflist .ctop.cdet.right.cfiles
17386066 272 listbox $cflist -bg white -selectmode extended -width $geometry(cflistw) \
d2610d11
PM
273 -yscrollcommand ".ctop.cdet.right.sb set"
274 scrollbar .ctop.cdet.right.sb -command "$cflist yview"
275 pack .ctop.cdet.right.sb -side right -fill y
276 pack $cflist -side left -fill both -expand 1
277 .ctop.cdet add .ctop.cdet.right
0fba86b3 278 bind .ctop.cdet <Configure> {resizecdetpanes %W %w}
d2610d11 279
0327d27a 280 pack .ctop -side top -fill both -expand 1
1db95b00 281
b5721c72
PM
282 bindall <1> {selcanvline %x %y}
283 bindall <B1-Motion> {selcanvline %x %y}
cfb4563c
PM
284 bindall <ButtonRelease-4> "allcanvs yview scroll -5 units"
285 bindall <ButtonRelease-5> "allcanvs yview scroll 5 units"
b5721c72
PM
286 bindall <2> "allcanvs scan mark 0 %y"
287 bindall <B2-Motion> "allcanvs scan dragto 0 %y"
17386066
PM
288 bind . <Key-Up> "selnextline -1"
289 bind . <Key-Down> "selnextline 1"
cfb4563c
PM
290 bind . <Key-Prior> "allcanvs yview scroll -1 pages"
291 bind . <Key-Next> "allcanvs yview scroll 1 pages"
292 bindkey <Key-Delete> "$ctext yview scroll -1 pages"
293 bindkey <Key-BackSpace> "$ctext yview scroll -1 pages"
294 bindkey <Key-space> "$ctext yview scroll 1 pages"
df3d83b1
PM
295 bindkey p "selnextline -1"
296 bindkey n "selnextline 1"
cfb4563c
PM
297 bindkey b "$ctext yview scroll -1 pages"
298 bindkey d "$ctext yview scroll 18 units"
299 bindkey u "$ctext yview scroll -18 units"
df3d83b1
PM
300 bindkey / findnext
301 bindkey ? findprev
39ad8570 302 bindkey f nextfile
1d10f36d 303 bind . <Control-q> doquit
98f350e5
PM
304 bind . <Control-f> dofind
305 bind . <Control-g> findnext
306 bind . <Control-r> findprev
1d10f36d
PM
307 bind . <Control-equal> {incrfont 1}
308 bind . <Control-KP_Add> {incrfont 1}
309 bind . <Control-minus> {incrfont -1}
310 bind . <Control-KP_Subtract> {incrfont -1}
e5c2d856 311 bind $cflist <<ListboxSelect>> listboxsel
0fba86b3 312 bind . <Destroy> {savestuff %W}
df3d83b1 313 bind . <Button-1> "click %W"
17386066 314 bind $fstring <Key-Return> dofind
887fe3c4 315 bind $sha1entry <Key-Return> gotocommit
df3d83b1
PM
316}
317
318# when we make a key binding for the toplevel, make sure
319# it doesn't get triggered when that key is pressed in the
320# find string entry widget.
321proc bindkey {ev script} {
887fe3c4 322 global entries
df3d83b1
PM
323 bind . $ev $script
324 set escript [bind Entry $ev]
325 if {$escript == {}} {
326 set escript [bind Entry <Key>]
327 }
887fe3c4
PM
328 foreach e $entries {
329 bind $e $ev "$escript; break"
330 }
df3d83b1
PM
331}
332
333# set the focus back to the toplevel for any click outside
887fe3c4 334# the entry widgets
df3d83b1 335proc click {w} {
887fe3c4
PM
336 global entries
337 foreach e $entries {
338 if {$w == $e} return
df3d83b1 339 }
887fe3c4 340 focus .
0fba86b3
PM
341}
342
343proc savestuff {w} {
344 global canv canv2 canv3 ctext cflist mainfont textfont
345 global stuffsaved
346 if {$stuffsaved} return
df3d83b1 347 if {![winfo viewable .]} return
0fba86b3
PM
348 catch {
349 set f [open "~/.gitk-new" w]
350 puts $f "set mainfont {$mainfont}"
351 puts $f "set textfont {$textfont}"
352 puts $f "set geometry(width) [winfo width .ctop]"
353 puts $f "set geometry(height) [winfo height .ctop]"
df3d83b1
PM
354 puts $f "set geometry(canv1) [expr [winfo width $canv]-2]"
355 puts $f "set geometry(canv2) [expr [winfo width $canv2]-2]"
356 puts $f "set geometry(canv3) [expr [winfo width $canv3]-2]"
357 puts $f "set geometry(canvh) [expr [winfo height $canv]-2]"
0fba86b3
PM
358 set wid [expr {([winfo width $ctext] - 8) \
359 / [font measure $textfont "0"]}]
0fba86b3 360 puts $f "set geometry(ctextw) $wid"
0fba86b3
PM
361 set wid [expr {([winfo width $cflist] - 11) \
362 / [font measure [$cflist cget -font] "0"]}]
363 puts $f "set geometry(cflistw) $wid"
364 close $f
365 file rename -force "~/.gitk-new" "~/.gitk"
366 }
367 set stuffsaved 1
1db95b00
PM
368}
369
43bddeb4
PM
370proc resizeclistpanes {win w} {
371 global oldwidth
372 if [info exists oldwidth($win)] {
373 set s0 [$win sash coord 0]
374 set s1 [$win sash coord 1]
375 if {$w < 60} {
376 set sash0 [expr {int($w/2 - 2)}]
377 set sash1 [expr {int($w*5/6 - 2)}]
378 } else {
379 set factor [expr {1.0 * $w / $oldwidth($win)}]
380 set sash0 [expr {int($factor * [lindex $s0 0])}]
381 set sash1 [expr {int($factor * [lindex $s1 0])}]
382 if {$sash0 < 30} {
383 set sash0 30
384 }
385 if {$sash1 < $sash0 + 20} {
386 set sash1 [expr $sash0 + 20]
387 }
388 if {$sash1 > $w - 10} {
389 set sash1 [expr $w - 10]
390 if {$sash0 > $sash1 - 20} {
391 set sash0 [expr $sash1 - 20]
392 }
393 }
394 }
395 $win sash place 0 $sash0 [lindex $s0 1]
396 $win sash place 1 $sash1 [lindex $s1 1]
397 }
398 set oldwidth($win) $w
399}
400
401proc resizecdetpanes {win w} {
402 global oldwidth
403 if [info exists oldwidth($win)] {
404 set s0 [$win sash coord 0]
405 if {$w < 60} {
406 set sash0 [expr {int($w*3/4 - 2)}]
407 } else {
408 set factor [expr {1.0 * $w / $oldwidth($win)}]
409 set sash0 [expr {int($factor * [lindex $s0 0])}]
410 if {$sash0 < 45} {
411 set sash0 45
412 }
413 if {$sash0 > $w - 15} {
414 set sash0 [expr $w - 15]
415 }
416 }
417 $win sash place 0 $sash0 [lindex $s0 1]
418 }
419 set oldwidth($win) $w
420}
421
b5721c72
PM
422proc allcanvs args {
423 global canv canv2 canv3
424 eval $canv $args
425 eval $canv2 $args
426 eval $canv3 $args
427}
428
429proc bindall {event action} {
430 global canv canv2 canv3
431 bind $canv $event $action
432 bind $canv2 $event $action
433 bind $canv3 $event $action
434}
435
9a40c50c
PM
436proc about {} {
437 set w .about
438 if {[winfo exists $w]} {
439 raise $w
440 return
441 }
442 toplevel $w
443 wm title $w "About gitk"
444 message $w.m -text {
cfb4563c 445Gitk version 1.1
9a40c50c
PM
446
447