blob: 1833fa86cee2415e670becd206de1d054feff61e [file] [log] [blame]
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001#!/bin/sh
2# Tcl ignores the next line -*- tcl -*- \
3exec wish "$0" -- "$@"
4
5# Copyright (C) 2006 Shawn Pearce, 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
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -050010######################################################################
11##
Shawn O. Pearcee210e672006-11-06 19:12:58 -050012## task management
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -050013
Shawn O. Pearceec6b4242006-11-06 20:50:59 -050014set single_commit 0
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -050015set status_active 0
Shawn O. Pearce131f5032006-11-06 16:07:32 -050016set diff_active 0
17set checkin_active 0
Shawn O. Pearceec6b4242006-11-06 20:50:59 -050018set commit_active 0
Shawn O. Pearce131f5032006-11-06 16:07:32 -050019set update_index_fd {}
20
Shawn O. Pearcee210e672006-11-06 19:12:58 -050021set disable_on_lock [list]
22set index_lock_type none
Shawn O. Pearce131f5032006-11-06 16:07:32 -050023
Shawn O. Pearcee57ca852006-11-06 21:34:10 -050024set HEAD {}
25set PARENT {}
26set commit_type {}
27
Shawn O. Pearcee210e672006-11-06 19:12:58 -050028proc lock_index {type} {
29 global index_lock_type disable_on_lock
30
31 if {$index_lock_type == {none}} {
32 set index_lock_type $type
33 foreach w $disable_on_lock {
34 uplevel #0 $w disabled
35 }
36 return 1
37 } elseif {$index_lock_type == {begin-update} && $type == {update}} {
38 set index_lock_type $type
Shawn O. Pearce131f5032006-11-06 16:07:32 -050039 return 1
40 }
41 return 0
42}
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -050043
Shawn O. Pearcee210e672006-11-06 19:12:58 -050044proc unlock_index {} {
45 global index_lock_type disable_on_lock
46
47 set index_lock_type none
48 foreach w $disable_on_lock {
49 uplevel #0 $w normal
50 }
51}
52
53######################################################################
54##
55## status
56
Shawn O. Pearceec6b4242006-11-06 20:50:59 -050057proc repository_state {hdvar ctvar} {
58 global gitdir
59 upvar $hdvar hd $ctvar ct
60
61 if {[catch {set hd [exec git rev-parse --verify HEAD]}]} {
62 set ct initial
63 } elseif {[file exists [file join $gitdir MERGE_HEAD]]} {
64 set ct merge
65 } else {
66 set ct normal
67 }
68}
69
Shawn O. Pearcee57ca852006-11-06 21:34:10 -050070proc update_status {{final Ready.}} {
71 global HEAD PARENT commit_type
Shawn O. Pearce131f5032006-11-06 16:07:32 -050072 global ui_index ui_other ui_status_value ui_comm
Shawn O. Pearce6b292672006-11-07 19:58:37 -050073 global status_active file_states status_start
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -050074
Shawn O. Pearcee210e672006-11-06 19:12:58 -050075 if {$status_active || ![lock_index read]} return
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -050076
Shawn O. Pearcee57ca852006-11-06 21:34:10 -050077 repository_state new_HEAD new_type
78 if {$commit_type == {amend}
79 && $new_type == {normal}
80 && $new_HEAD == $HEAD} {
81 } else {
82 set HEAD $new_HEAD
83 set PARENT $new_HEAD
84 set commit_type $new_type
85 }
86
Shawn O. Pearce6b292672006-11-07 19:58:37 -050087 set status_start [clock seconds]
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -050088 array unset file_states
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -050089 foreach w [list $ui_index $ui_other] {
90 $w conf -state normal
91 $w delete 0.0 end
92 $w conf -state disabled
93 }
94
Shawn O. Pearce131f5032006-11-06 16:07:32 -050095 if {![$ui_comm edit modified]
Shawn O. Pearcecc4b1c02006-11-06 23:47:05 -050096 || [string trim [$ui_comm get 0.0 end]] == {}} {
Shawn O. Pearce131f5032006-11-06 16:07:32 -050097 if {[load_message GITGUI_MSG]} {
98 } elseif {[load_message MERGE_MSG]} {
99 } elseif {[load_message SQUASH_MSG]} {
100 }
101 $ui_comm edit modified false
102 }
103
104 set status_active 1
105 set ui_status_value {Refreshing file status...}
106 set fd_rf [open "| git update-index -q --unmerged --refresh" r]
107 fconfigure $fd_rf -blocking 0 -translation binary
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500108 fileevent $fd_rf readable [list read_refresh $fd_rf $final]
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500109}
110
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500111proc read_refresh {fd final} {
112 global gitdir PARENT commit_type
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500113 global ui_index ui_other ui_status_value ui_comm
114 global status_active file_states
Shawn O. Pearce868c8752006-11-07 18:34:09 -0500115 global buf_rdi buf_rdf buf_rlo
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500116
117 read $fd
118 if {![eof $fd]} return
119 close $fd
120
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500121 set ls_others [list | git ls-files --others -z \
122 --exclude-per-directory=.gitignore]
123 set info_exclude [file join $gitdir info exclude]
124 if {[file readable $info_exclude]} {
125 lappend ls_others "--exclude-from=$info_exclude"
126 }
127
Shawn O. Pearce868c8752006-11-07 18:34:09 -0500128 set buf_rdi {}
129 set buf_rdf {}
130 set buf_rlo {}
131
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500132 set status_active 3
133 set ui_status_value {Scanning for modified files ...}
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500134 set fd_di [open "| git diff-index --cached -z $PARENT" r]
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500135 set fd_df [open "| git diff-files -z" r]
136 set fd_lo [open $ls_others r]
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500137
138 fconfigure $fd_di -blocking 0 -translation binary
139 fconfigure $fd_df -blocking 0 -translation binary
140 fconfigure $fd_lo -blocking 0 -translation binary
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500141 fileevent $fd_di readable [list read_diff_index $fd_di $final]
142 fileevent $fd_df readable [list read_diff_files $fd_df $final]
143 fileevent $fd_lo readable [list read_ls_others $fd_lo $final]
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500144}
145
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500146proc load_message {file} {
147 global gitdir ui_comm
148
149 set f [file join $gitdir $file]
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500150 if {[file isfile $f]} {
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500151 if {[catch {set fd [open $f r]}]} {
152 return 0
153 }
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500154 set content [string trim [read $fd]]
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500155 close $fd
156 $ui_comm delete 0.0 end
157 $ui_comm insert end $content
158 return 1
159 }
160 return 0
161}
162
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500163proc read_diff_index {fd final} {
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500164 global buf_rdi
165
166 append buf_rdi [read $fd]
Shawn O. Pearce868c8752006-11-07 18:34:09 -0500167 set c 0
168 set n [string length $buf_rdi]
169 while {$c < $n} {
170 set z1 [string first "\0" $buf_rdi $c]
171 if {$z1 == -1} break
172 incr z1
173 set z2 [string first "\0" $buf_rdi $z1]
174 if {$z2 == -1} break
175
176 set c $z2
177 incr z2 -1
178 display_file \
179 [string range $buf_rdi $z1 $z2] \
180 [string index $buf_rdi [expr $z1 - 2]]_
181 incr c
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500182 }
Shawn O. Pearce868c8752006-11-07 18:34:09 -0500183 if {$c < $n} {
184 set buf_rdi [string range $buf_rdi $c end]
185 } else {
186 set buf_rdi {}
187 }
188
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500189 status_eof $fd buf_rdi $final
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500190}
191
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500192proc read_diff_files {fd final} {
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500193 global buf_rdf
194
195 append buf_rdf [read $fd]
Shawn O. Pearce868c8752006-11-07 18:34:09 -0500196 set c 0
197 set n [string length $buf_rdf]
198 while {$c < $n} {
199 set z1 [string first "\0" $buf_rdf $c]
200 if {$z1 == -1} break
201 incr z1
202 set z2 [string first "\0" $buf_rdf $z1]
203 if {$z2 == -1} break
204
205 set c $z2
206 incr z2 -1
207 display_file \
208 [string range $buf_rdf $z1 $z2] \
209 _[string index $buf_rdf [expr $z1 - 2]]
210 incr c
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500211 }
Shawn O. Pearce868c8752006-11-07 18:34:09 -0500212 if {$c < $n} {
213 set buf_rdf [string range $buf_rdf $c end]
214 } else {
215 set buf_rdf {}
216 }
217
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500218 status_eof $fd buf_rdf $final
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500219}
220
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500221proc read_ls_others {fd final} {
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500222 global buf_rlo
223
224 append buf_rlo [read $fd]
225 set pck [split $buf_rlo "\0"]
226 set buf_rlo [lindex $pck end]
227 foreach p [lrange $pck 0 end-1] {
228 display_file $p _O
229 }
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500230 status_eof $fd buf_rlo $final
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500231}
232
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500233proc status_eof {fd buf final} {
Shawn O. Pearce6b292672006-11-07 19:58:37 -0500234 global status_active status_start $buf
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500235 global ui_fname_value ui_status_value file_states
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500236
237 if {[eof $fd]} {
238 set $buf {}
239 close $fd
Shawn O. Pearce93f654d2006-11-07 19:30:54 -0500240
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500241 if {[incr status_active -1] == 0} {
Shawn O. Pearcee210e672006-11-06 19:12:58 -0500242 unlock_index
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500243
Shawn O. Pearce6b292672006-11-07 19:58:37 -0500244 set e1 [clock seconds]
Shawn O. Pearce93f654d2006-11-07 19:30:54 -0500245 display_all_files
Shawn O. Pearce6b292672006-11-07 19:58:37 -0500246 set e2 [clock seconds]
247puts "TIME [expr $e1 - $status_start] + [expr $e2 - $e1] = [expr $e2 - $status_start]"
248
249 set ui_status_value $final
Shawn O. Pearce93f654d2006-11-07 19:30:54 -0500250
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500251 if {$ui_fname_value != {} && [array names file_states \
252 -exact $ui_fname_value] != {}} {
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500253 show_diff $ui_fname_value
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500254 } else {
255 clear_diff
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500256 }
257 }
258 }
259}
260
261######################################################################
262##
263## diff
264
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500265proc clear_diff {} {
266 global ui_diff ui_fname_value ui_fstatus_value
267
268 $ui_diff conf -state normal
269 $ui_diff delete 0.0 end
270 $ui_diff conf -state disabled
271 set ui_fname_value {}
272 set ui_fstatus_value {}
273}
274
275proc show_diff {path} {
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500276 global file_states PARENT diff_3way diff_active
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500277 global ui_diff ui_fname_value ui_fstatus_value ui_status_value
278
Shawn O. Pearcee210e672006-11-06 19:12:58 -0500279 if {$diff_active || ![lock_index read]} return
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500280
281 clear_diff
282 set s $file_states($path)
283 set m [lindex $s 0]
284 set diff_3way 0
285 set diff_active 1
286 set ui_fname_value $path
287 set ui_fstatus_value [mapdesc $m $path]
288 set ui_status_value "Loading diff of $path..."
289
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500290 set cmd [list | git diff-index -p $PARENT -- $path]
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500291 switch $m {
292 AM {
293 }
294 MM {
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500295 set cmd [list | git diff-index -p -c $PARENT $path]
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500296 }
297 _O {
298 if {[catch {
299 set fd [open $path r]
300 set content [read $fd]
301 close $fd
302 } err ]} {
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500303 set diff_active 0
Shawn O. Pearcee210e672006-11-06 19:12:58 -0500304 unlock_index
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500305 set ui_status_value "Unable to display $path"
306 error_popup "Error loading file:\n$err"
307 return
308 }
309 $ui_diff conf -state normal
310 $ui_diff insert end $content
311 $ui_diff conf -state disabled
Shawn O. Pearcebd1e2b42006-11-06 22:03:05 -0500312 set diff_active 0
313 unlock_index
314 set ui_status_value {Ready.}
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500315 return
316 }
317 }
318
319 if {[catch {set fd [open $cmd r]} err]} {
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500320 set diff_active 0
Shawn O. Pearcee210e672006-11-06 19:12:58 -0500321 unlock_index
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500322 set ui_status_value "Unable to display $path"
323 error_popup "Error loading diff:\n$err"
324 return
325 }
326
Shawn O. Pearce6f6eed22006-11-06 18:22:19 -0500327 fconfigure $fd -blocking 0 -translation auto
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500328 fileevent $fd readable [list read_diff $fd]
329}
330
331proc read_diff {fd} {
332 global ui_diff ui_status_value diff_3way diff_active
333
334 while {[gets $fd line] >= 0} {
Shawn O. Pearce6f6eed22006-11-06 18:22:19 -0500335 if {[string match {diff --git *} $line]} continue
336 if {[string match {diff --combined *} $line]} continue
337 if {[string match {--- *} $line]} continue
338 if {[string match {+++ *} $line]} continue
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500339 if {[string match index* $line]} {
340 if {[string first , $line] >= 0} {
341 set diff_3way 1
342 }
343 }
344
345 $ui_diff conf -state normal
346 if {!$diff_3way} {
347 set x [string index $line 0]
348 switch -- $x {
349 "@" {set tags da}
350 "+" {set tags dp}
351 "-" {set tags dm}
352 default {set tags {}}
353 }
354 } else {
355 set x [string range $line 0 1]
356 switch -- $x {
357 default {set tags {}}
358 "@@" {set tags da}
359 "++" {set tags dp; set x " +"}
360 " +" {set tags {di bold}; set x "++"}
361 "+ " {set tags dni; set x "-+"}
362 "--" {set tags dm; set x " -"}
363 " -" {set tags {dm bold}; set x "--"}
364 "- " {set tags di; set x "+-"}
365 default {set tags {}}
366 }
367 set line [string replace $line 0 1 $x]
368 }
369 $ui_diff insert end $line $tags
370 $ui_diff insert end "\n"
371 $ui_diff conf -state disabled
372 }
373
374 if {[eof $fd]} {
375 close $fd
376 set diff_active 0
Shawn O. Pearcee210e672006-11-06 19:12:58 -0500377 unlock_index
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500378 set ui_status_value {Ready.}
379 }
380}
381
382######################################################################
383##
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500384## commit
385
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500386proc load_last_commit {} {
387 global HEAD PARENT commit_type ui_comm
388
389 if {$commit_type == {amend}} return
390 if {$commit_type != {normal}} {
391 error_popup "Can't amend a $commit_type commit."
392 return
393 }
394
395 set msg {}
396 set parent {}
397 set parent_count 0
398 if {[catch {
399 set fd [open "| git cat-file commit $HEAD" r]
400 while {[gets $fd line] > 0} {
401 if {[string match {parent *} $line]} {
402 set parent [string range $line 7 end]
403 incr parent_count
404 }
405 }
406 set msg [string trim [read $fd]]
407 close $fd
408 } err]} {
409 error_popup "Error loading commit data for amend:\n$err"
410 return
411 }
412
413 if {$parent_count == 0} {
414 set commit_type amend
415 set HEAD {}
416 set PARENT {}
417 update_status
418 } elseif {$parent_count == 1} {
419 set commit_type amend
420 set PARENT $parent
421 $ui_comm delete 0.0 end
422 $ui_comm insert end $msg
423 $ui_comm edit modified false
424 update_status
425 } else {
426 error_popup {You can't amend a merge commit.}
427 return
428 }
429}
430
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500431proc commit_tree {} {
432 global tcl_platform HEAD gitdir commit_type file_states
433 global commit_active ui_status_value
434 global ui_comm
435
436 if {$commit_active || ![lock_index update]} return
437
438 # -- Our in memory state should match the repository.
439 #
440 repository_state curHEAD cur_type
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500441 if {$commit_type == {amend}
442 && $cur_type == {normal}
443 && $curHEAD == $HEAD} {
444 } elseif {$commit_type != $cur_type || $HEAD != $curHEAD} {
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500445 error_popup {Last scanned state does not match repository state.
446
447Its highly likely that another Git program modified the
448repository since our last scan. A rescan is required
449before committing.
450}
451 unlock_index
452 update_status
453 return
454 }
455
456 # -- At least one file should differ in the index.
457 #
458 set files_ready 0
459 foreach path [array names file_states] {
460 set s $file_states($path)
461 switch -glob -- [lindex $s 0] {
462 _* {continue}
463 A* -
464 D* -
465 M* {set files_ready 1; break}
466 U* {
467 error_popup "Unmerged files cannot be committed.
468
469File $path has merge conflicts.
470You must resolve them and check the file in before committing.
471"
472 unlock_index
473 return
474 }
475 default {
476 error_popup "Unknown file state [lindex $s 0] detected.
477
478File $path cannot be committed by this program.
479"
480 }
481 }
482 }
483 if {!$files_ready} {
484 error_popup {No checked-in files to commit.
485
486You must check-in at least 1 file before you can commit.
487}
488 unlock_index
489 return
490 }
491
492 # -- A message is required.
493 #
494 set msg [string trim [$ui_comm get 1.0 end]]
495 if {$msg == {}} {
496 error_popup {Please supply a commit message.
497
498A good commit message has the following format:
499
500- First line: Describe in one sentance what you did.
501- Second line: Blank
502- Remaining lines: Describe why this change is good.
503}
504 unlock_index
505 return
506 }
507
508 # -- Ask the pre-commit hook for the go-ahead.
509 #
510 set pchook [file join $gitdir hooks pre-commit]
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500511 if {$tcl_platform(platform) == {windows} && [file isfile $pchook]} {
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500512 set pchook [list sh -c \
513 "if test -x \"$pchook\"; then exec \"$pchook\"; fi"]
514 } elseif {[file executable $pchook]} {
515 set pchook [list $pchook]
516 } else {
517 set pchook {}
518 }
519 if {$pchook != {} && [catch {eval exec $pchook} err]} {
520 hook_failed_popup pre-commit $err
521 unlock_index
522 return
523 }
524
525 # -- Write the tree in the background.
526 #
527 set commit_active 1
528 set ui_status_value {Committing changes...}
529
530 set fd_wt [open "| git write-tree" r]
Shawn O. Pearcebd1e2b42006-11-06 22:03:05 -0500531 fileevent $fd_wt readable [list commit_stage2 $fd_wt $curHEAD $msg]
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500532}
533
534proc commit_stage2 {fd_wt curHEAD msg} {
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500535 global single_commit gitdir PARENT commit_type
536 global commit_active ui_status_value ui_comm
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500537
538 gets $fd_wt tree_id
539 close $fd_wt
540
541 if {$tree_id == {}} {
542 error_popup "write-tree failed"
543 set commit_active 0
544 set ui_status_value {Commit failed.}
545 unlock_index
546 return
547 }
548
549 # -- Create the commit.
550 #
551 set cmd [list git commit-tree $tree_id]
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500552 if {$PARENT != {}} {
553 lappend cmd -p $PARENT
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500554 }
555 if {$commit_type == {merge}} {
556 if {[catch {
557 set fd_mh [open [file join $gitdir MERGE_HEAD] r]
Shawn O. Pearcebd1e2b42006-11-06 22:03:05 -0500558 while {[gets $fd_mh merge_head] >= 0} {
559 lappend cmd -p $merge_head
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500560 }
561 close $fd_mh
562 } err]} {
563 error_popup "Loading MERGE_HEADs failed:\n$err"
564 set commit_active 0
565 set ui_status_value {Commit failed.}
566 unlock_index
567 return
568 }
569 }
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500570 if {$PARENT == {}} {
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500571 # git commit-tree writes to stderr during initial commit.
572 lappend cmd 2>/dev/null
573 }
574 lappend cmd << $msg
575 if {[catch {set cmt_id [eval exec $cmd]} err]} {
576 error_popup "commit-tree failed:\n$err"
577 set commit_active 0
578 set ui_status_value {Commit failed.}
579 unlock_index
580 return
581 }
582
583 # -- Update the HEAD ref.
584 #
585 set reflogm commit
586 if {$commit_type != {normal}} {
587 append reflogm " ($commit_type)"
588 }
589 set i [string first "\n" $msg]
590 if {$i >= 0} {
591 append reflogm {: } [string range $msg 0 [expr $i - 1]]
592 } else {
593 append reflogm {: } $msg
594 }
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500595 set cmd [list git update-ref -m $reflogm HEAD $cmt_id $curHEAD]
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500596 if {[catch {eval exec $cmd} err]} {
597 error_popup "update-ref failed:\n$err"
598 set commit_active 0
599 set ui_status_value {Commit failed.}
600 unlock_index
601 return
602 }
603
604 # -- Cleanup after ourselves.
605 #
606 catch {file delete [file join $gitdir MERGE_HEAD]}
607 catch {file delete [file join $gitdir MERGE_MSG]}
608 catch {file delete [file join $gitdir SQUASH_MSG]}
609 catch {file delete [file join $gitdir GITGUI_MSG]}
610
611 # -- Let rerere do its thing.
612 #
613 if {[file isdirectory [file join $gitdir rr-cache]]} {
614 catch {exec git rerere}
615 }
616
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500617 $ui_comm delete 0.0 end
618 $ui_comm edit modified false
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500619
620 if {$single_commit} do_quit
621
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500622 set commit_type {}
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500623 set commit_active 0
Shawn O. Pearcebd1e2b42006-11-06 22:03:05 -0500624 set HEAD $cmt_id
625 set PARENT $cmt_id
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500626 unlock_index
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500627 update_status "Changes committed as $cmt_id."
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500628}
629
630######################################################################
631##
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500632## fetch pull push
633
634proc fetch_from {remote} {
635 set w [new_console "fetch $remote" \
636 "Fetching new changes from $remote"]
Shawn O. Pearcecc4b1c02006-11-06 23:47:05 -0500637 set cmd [list git fetch]
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500638 lappend cmd $remote
Shawn O. Pearcecc4b1c02006-11-06 23:47:05 -0500639 console_exec $w $cmd
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500640}
641
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -0500642proc pull_remote {remote branch} {
643 set w [new_console "pull $remote $branch" \
644 "Pulling new changes from branch $branch in $remote"]
645 set cmd [list git pull]
646 lappend cmd $remote
647 lappend cmd $branch
648 console_exec $w $cmd [list post_pull_remote $remote $branch]
649}
650
651proc post_pull_remote {remote branch success} {
652 if {$success} {
653 update_status "Successfully pulled $branch from $remote."
654 } else {
655 update_status "Conflicts detected while pulling $branch from $remote."
656 }
657}
658
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500659proc push_to {remote} {
660 set w [new_console "push $remote" \
661 "Pushing changes to $remote"]
Shawn O. Pearcecc4b1c02006-11-06 23:47:05 -0500662 set cmd [list git push]
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500663 lappend cmd $remote
Shawn O. Pearcecc4b1c02006-11-06 23:47:05 -0500664 console_exec $w $cmd
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500665}
666
667######################################################################
668##
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500669## ui helpers
670
671proc mapcol {state path} {
Shawn O. Pearce6b292672006-11-07 19:58:37 -0500672 global all_cols ui_other
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500673
674 if {[catch {set r $all_cols($state)}]} {
675 puts "error: no column for state={$state} $path"
Shawn O. Pearce6b292672006-11-07 19:58:37 -0500676 return $ui_other
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500677 }
678 return $r
679}
680
681proc mapicon {state path} {
682 global all_icons
683
684 if {[catch {set r $all_icons($state)}]} {
685 puts "error: no icon for state={$state} $path"
686 return file_plain
687 }
688 return $r
689}
690
691proc mapdesc {state path} {
692 global all_descs
693
694 if {[catch {set r $all_descs($state)}]} {
695 puts "error: no desc for state={$state} $path"
696 return $state
697 }
698 return $r
699}
700
701proc bsearch {w path} {
702 set hi [expr [lindex [split [$w index end] .] 0] - 2]
703 if {$hi == 0} {
704 return -1
705 }
706 set lo 0
707 while {$lo < $hi} {
708 set mi [expr [expr $lo + $hi] / 2]
709 set ti [expr $mi + 1]
710 set cmp [string compare [$w get $ti.1 $ti.end] $path]
711 if {$cmp < 0} {
712 set lo $ti
713 } elseif {$cmp == 0} {
714 return $mi
715 } else {
716 set hi $mi
717 }
718 }
719 return -[expr $lo + 1]
720}
721
Shawn O. Pearce93f654d2006-11-07 19:30:54 -0500722set next_icon_id 0
723
Shawn O. Pearce6b292672006-11-07 19:58:37 -0500724proc merge_state {path new_state} {
Shawn O. Pearce93f654d2006-11-07 19:30:54 -0500725 global file_states next_icon_id
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500726
Shawn O. Pearce6b292672006-11-07 19:58:37 -0500727 set s0 [string index $new_state 0]
728 set s1 [string index $new_state 1]
729
730 if {[catch {set info $file_states($path)}]} {
731 set state __
732 set icon n[incr next_icon_id]
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500733 } else {
Shawn O. Pearce6b292672006-11-07 19:58:37 -0500734 set state [lindex $info 0]
735 set icon [lindex $info 1]
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500736 }
737
Shawn O. Pearce6b292672006-11-07 19:58:37 -0500738 if {$s0 == {_}} {
739 set s0 [string index $state 0]
740 } elseif {$s0 == {*}} {
741 set s0 _
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500742 }
743
Shawn O. Pearce6b292672006-11-07 19:58:37 -0500744 if {$s1 == {_}} {
745 set s1 [string index $state 1]
746 } elseif {$s1 == {*}} {
747 set s1 _
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500748 }
749
Shawn O. Pearce6b292672006-11-07 19:58:37 -0500750 set file_states($path) [list $s0$s1 $icon]
751 return $state
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500752}
753
754proc display_file {path state} {
Shawn O. Pearce93f654d2006-11-07 19:30:54 -0500755 global ui_index ui_other file_states status_active
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500756
757 set old_m [merge_state $path $state]
Shawn O. Pearce93f654d2006-11-07 19:30:54 -0500758 if {$status_active} return
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500759
Shawn O. Pearce93f654d2006-11-07 19:30:54 -0500760 set s $file_states($path)
Shawn O. Pearce6b292672006-11-07 19:58:37 -0500761 set old_w [mapcol $old_m $path]
762 set new_w [mapcol $new_m $path]
Shawn O. Pearce93f654d2006-11-07 19:30:54 -0500763 set new_m [lindex $s 0]
Shawn O. Pearce93f654d2006-11-07 19:30:54 -0500764 set new_ico [mapicon $new_m $path]
765
Shawn O. Pearce6b292672006-11-07 19:58:37 -0500766 if {$new_w != $old_w} {
Shawn O. Pearce93f654d2006-11-07 19:30:54 -0500767 set lno [bsearch $old_w $path]
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500768 if {$lno >= 0} {
769 incr lno
Shawn O. Pearce93f654d2006-11-07 19:30:54 -0500770 $old_w conf -state normal
771 $old_w delete $lno.0 [expr $lno + 1].0
772 $old_w conf -state disabled
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500773 }
Shawn O. Pearce93f654d2006-11-07 19:30:54 -0500774
775 set lno [expr abs([bsearch $new_w $path] + 1) + 1]
776 $new_w conf -state normal
777 $new_w image create $lno.0 \
778 -align center -padx 5 -pady 1 \
779 -name [lindex $s 1] \
780 -image [mapicon $m $path]
781 $new_w insert $lno.1 "$path\n"
782 $new_w conf -state disabled
783 } elseif {$new_icon != [mapicon $old_m $path]} {
784 $new_w conf -state normal
785 $new_w image conf [lindex $s 1] -image $new_icon
786 $new_w conf -state disabled
787 }
788}
789
790proc display_all_files {} {
791 global ui_index ui_other file_states
792
793 $ui_index conf -state normal
794 $ui_other conf -state normal
795
796 foreach path [lsort [array names file_states]] {
797 set s $file_states($path)
798 set m [lindex $s 0]
Shawn O. Pearce6b292672006-11-07 19:58:37 -0500799 set w [mapcol $m $path]
800 $w image create end \
Shawn O. Pearce93f654d2006-11-07 19:30:54 -0500801 -align center -padx 5 -pady 1 \
802 -name [lindex $s 1] \
803 -image [mapicon $m $path]
Shawn O. Pearce6b292672006-11-07 19:58:37 -0500804 $w insert end "$path\n"
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500805 }
806
Shawn O. Pearce93f654d2006-11-07 19:30:54 -0500807 $ui_index conf -state disabled
808 $ui_other conf -state disabled
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500809}
810
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500811proc with_update_index {body} {
812 global update_index_fd
813
814 if {$update_index_fd == {}} {
Shawn O. Pearcee210e672006-11-06 19:12:58 -0500815 if {![lock_index update]} return
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500816 set update_index_fd [open \
817 "| git update-index --add --remove -z --stdin" \
818 w]
819 fconfigure $update_index_fd -translation binary
820 uplevel 1 $body
821 close $update_index_fd
822 set update_index_fd {}
Shawn O. Pearcee210e672006-11-06 19:12:58 -0500823 unlock_index
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500824 } else {
825 uplevel 1 $body
826 }
827}
828
829proc update_index {path} {
830 global update_index_fd
831
832 if {$update_index_fd == {}} {
833 error {not in with_update_index}
834 } else {
835 puts -nonewline $update_index_fd "$path\0"
836 }
837}
838
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500839proc toggle_mode {path} {
Shawn O. Pearcebd1e2b42006-11-06 22:03:05 -0500840 global file_states ui_fname_value
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500841
842 set s $file_states($path)
843 set m [lindex $s 0]
844
845 switch -- $m {
846 AM -
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500847 _O {set new A*}
848 _M -
849 MM {set new M*}
Shawn O. Pearcebd1e2b42006-11-06 22:03:05 -0500850 AD -
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500851 _D {set new D*}
852 default {return}
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500853 }
854
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500855 with_update_index {update_index $path}
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500856 display_file $path $new
Shawn O. Pearcebd1e2b42006-11-06 22:03:05 -0500857 if {$ui_fname_value == $path} {
858 show_diff $path
859 }
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500860}
861
862######################################################################
863##
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500864## config (fetch push pull)
865
Shawn O. Pearce0d4f3eb2006-11-07 04:26:02 -0500866proc load_repo_config {} {
867 global repo_config
868
869 array unset repo_config
870 catch {
871 set fd_rc [open "| git repo-config --list" r]
872 while {[gets $fd_rc line] >= 0} {
873 if {[regexp {^([^=]+)=(.*)$} $line line name value]} {
874 lappend repo_config($name) $value
875 }
876 }
877 close $fd_rc
878 }
879}
880
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500881proc load_all_remotes {} {
Shawn O. Pearce0d4f3eb2006-11-07 04:26:02 -0500882 global gitdir all_remotes repo_config
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500883
884 set all_remotes [list]
885 set rm_dir [file join $gitdir remotes]
886 if {[file isdirectory $rm_dir]} {
Shawn O. Pearced47ae542006-11-07 03:00:20 -0500887 set all_remotes [concat $all_remotes [glob \
888 -types f \
889 -tails \
890 -nocomplain \
891 -directory $rm_dir *]]
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500892 }
893
Shawn O. Pearce0d4f3eb2006-11-07 04:26:02 -0500894 foreach line [array names repo_config remote.*.url] {
895 if {[regexp ^remote\.(.*)\.url\$ $line line name]} {
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500896 lappend all_remotes $name
897 }
898 }
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500899
900 set all_remotes [lsort -unique $all_remotes]
901}
902
903proc populate_remote_menu {m pfx op} {
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -0500904 global all_remotes mainfont
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500905
906 foreach remote $all_remotes {
907 $m add command -label "$pfx $remote..." \
908 -command [list $op $remote] \
909 -font $mainfont
910 }
911}
912
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -0500913proc populate_pull_menu {m} {
914 global gitdir repo_config all_remotes mainfont
915
916 foreach remote $all_remotes {
917 set rb {}
918 if {[array get repo_config remote.$remote.url] != {}} {
919 if {[array get repo_config remote.$remote.fetch] != {}} {
920 regexp {^([^:]+):} \
921 [lindex $repo_config(remote.$remote.fetch) 0] \
922 line rb
923 }
924 } else {
925 catch {
926 set fd [open [file join $gitdir remotes $remote] r]
927 while {[gets $fd line] >= 0} {
928 if {[regexp {^Pull:[ \t]*([^:]+):} $line line rb]} {
929 break
930 }
931 }
932 close $fd
933 }
934 }
935
936 set rb_short $rb
937 regsub ^refs/heads/ $rb {} rb_short
938 if {$rb_short != {}} {
939 $m add command \
940 -label "Branch $rb_short from $remote..." \
941 -command [list pull_remote $remote $rb] \
942 -font $mainfont
943 }
944 }
945}
946
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500947######################################################################
948##
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500949## icons
950
951set filemask {
952#define mask_width 14
953#define mask_height 15
954static unsigned char mask_bits[] = {
955 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f,
956 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f,
957 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f};
958}
959
960image create bitmap file_plain -background white -foreground black -data {
961#define plain_width 14
962#define plain_height 15
963static unsigned char plain_bits[] = {
964 0xfe, 0x01, 0x02, 0x03, 0x02, 0x05, 0x02, 0x09, 0x02, 0x1f, 0x02, 0x10,
965 0x02, 0x10, 0x02, 0x10, 0x02, 0x10, 0x02, 0x10, 0x02, 0x10, 0x02, 0x10,
966 0x02, 0x10, 0x02, 0x10, 0xfe, 0x1f};
967} -maskdata $filemask
968
969image create bitmap file_mod -background white -foreground blue -data {
970#define mod_width 14
971#define mod_height 15
972static unsigned char mod_bits[] = {
973 0xfe, 0x01, 0x02, 0x03, 0x7a, 0x05, 0x02, 0x09, 0x7a, 0x1f, 0x02, 0x10,
974 0xfa, 0x17, 0x02, 0x10, 0xfa, 0x17, 0x02, 0x10, 0xfa, 0x17, 0x02, 0x10,
975 0xfa, 0x17, 0x02, 0x10, 0xfe, 0x1f};
976} -maskdata $filemask
977
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500978image create bitmap file_fulltick -background white -foreground "#007000" -data {
979#define file_fulltick_width 14
980#define file_fulltick_height 15
981static unsigned char file_fulltick_bits[] = {
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500982 0xfe, 0x01, 0x02, 0x1a, 0x02, 0x0c, 0x02, 0x0c, 0x02, 0x16, 0x02, 0x16,
983 0x02, 0x13, 0x00, 0x13, 0x86, 0x11, 0x8c, 0x11, 0xd8, 0x10, 0xf2, 0x10,
984 0x62, 0x10, 0x02, 0x10, 0xfe, 0x1f};
985} -maskdata $filemask
986
987image create bitmap file_parttick -background white -foreground "#005050" -data {
988#define parttick_width 14
989#define parttick_height 15
990static unsigned char parttick_bits[] = {
991 0xfe, 0x01, 0x02, 0x03, 0x7a, 0x05, 0x02, 0x09, 0x7a, 0x1f, 0x02, 0x10,
992 0x7a, 0x14, 0x02, 0x16, 0x02, 0x13, 0x8a, 0x11, 0xda, 0x10, 0x72, 0x10,
993 0x22, 0x10, 0x02, 0x10, 0xfe, 0x1f};
994} -maskdata $filemask
995
996image create bitmap file_question -background white -foreground black -data {
997#define file_question_width 14
998#define file_question_height 15
999static unsigned char file_question_bits[] = {
1000 0xfe, 0x01, 0x02, 0x02, 0xe2, 0x04, 0xf2, 0x09, 0x1a, 0x1b, 0x0a, 0x13,
1001 0x82, 0x11, 0xc2, 0x10, 0x62, 0x10, 0x62, 0x10, 0x02, 0x10, 0x62, 0x10,
1002 0x62, 0x10, 0x02, 0x10, 0xfe, 0x1f};
1003} -maskdata $filemask
1004
1005image create bitmap file_removed -background white -foreground red -data {
1006#define file_removed_width 14
1007#define file_removed_height 15
1008static unsigned char file_removed_bits[] = {
1009 0xfe, 0x01, 0x02, 0x03, 0x02, 0x05, 0x02, 0x09, 0x02, 0x1f, 0x02, 0x10,
1010 0x1a, 0x16, 0x32, 0x13, 0xe2, 0x11, 0xc2, 0x10, 0xe2, 0x11, 0x32, 0x13,
1011 0x1a, 0x16, 0x02, 0x10, 0xfe, 0x1f};
1012} -maskdata $filemask
1013
1014image create bitmap file_merge -background white -foreground blue -data {
1015#define file_merge_width 14
1016#define file_merge_height 15
1017static unsigned char file_merge_bits[] = {
1018 0xfe, 0x01, 0x02, 0x03, 0x62, 0x05, 0x62, 0x09, 0x62, 0x1f, 0x62, 0x10,
1019 0xfa, 0x11, 0xf2, 0x10, 0x62, 0x10, 0x02, 0x10, 0xfa, 0x17, 0x02, 0x10,
1020 0xfa, 0x17, 0x02, 0x10, 0xfe, 0x1f};
1021} -maskdata $filemask
1022
Shawn O. Pearce6b292672006-11-07 19:58:37 -05001023set ui_index .vpane.files.index.list
1024set ui_other .vpane.files.other.list
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001025set max_status_desc 0
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001026foreach i {
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001027 {__ i plain "Unmodified"}
1028 {_M i mod "Modified"}
1029 {M_ i fulltick "Checked in"}
1030 {MM i parttick "Partially checked in"}
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001031
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001032 {_O o plain "Untracked"}
1033 {A_ o fulltick "Added"}
1034 {AM o parttick "Partially added"}
Shawn O. Pearce6b292672006-11-07 19:58:37 -05001035 {AD o question "Added (but now gone)"}
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001036
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001037 {_D i question "Missing"}
1038 {D_ i removed "Removed"}
1039 {DD i removed "Removed"}
1040 {DO i removed "Removed (still exists)"}
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001041
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001042 {UM i merge "Merge conflicts"}
1043 {U_ i merge "Merge conflicts"}
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001044 } {
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001045 if {$max_status_desc < [string length [lindex $i 3]]} {
1046 set max_status_desc [string length [lindex $i 3]]
1047 }
Shawn O. Pearce6b292672006-11-07 19:58:37 -05001048 if {[lindex $i 1] == {i}} {
1049 set all_cols([lindex $i 0]) $ui_index
1050 } else {
1051 set all_cols([lindex $i 0]) $ui_other
1052 }
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001053 set all_icons([lindex $i 0]) file_[lindex $i 2]
1054 set all_descs([lindex $i 0]) [lindex $i 3]
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001055}
1056unset filemask i
1057
1058######################################################################
1059##
1060## util
1061
1062proc error_popup {msg} {
1063 set w .error
1064 toplevel $w
1065 wm transient $w .
1066 show_msg $w $w $msg
1067}
1068
1069proc show_msg {w top msg} {
Shawn O. Pearceb8ce6f02006-11-07 00:20:56 -05001070 global gitdir appname mainfont
Shawn O. Pearce6e27d822006-11-06 20:03:36 -05001071
1072 message $w.m -text $msg -justify left -aspect 400
Shawn O. Pearceec6b4242006-11-06 20:50:59 -05001073 pack $w.m -side top -fill x -padx 5 -pady 10
1074 button $w.ok -text OK \
1075 -width 15 \
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001076 -font $mainfont \
Shawn O. Pearceec6b4242006-11-06 20:50:59 -05001077 -command "destroy $top"
Shawn O. Pearce6e27d822006-11-06 20:03:36 -05001078 pack $w.ok -side bottom
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001079 bind $top <Visibility> "grab $top; focus $top"
1080 bind $top <Key-Return> "destroy $top"
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -05001081 wm title $w "$appname ([lindex [file split \
1082 [file normalize [file dirname $gitdir]]] \
1083 end]): error"
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001084 tkwait window $top
1085}
1086
Shawn O. Pearce6e27d822006-11-06 20:03:36 -05001087proc hook_failed_popup {hook msg} {
Shawn O. Pearceec6b4242006-11-06 20:50:59 -05001088 global gitdir mainfont difffont appname
Shawn O. Pearce6e27d822006-11-06 20:03:36 -05001089
1090 set w .hookfail
1091 toplevel $w
1092 wm transient $w .
1093
1094 frame $w.m
1095 label $w.m.l1 -text "$hook hook failed:" \
1096 -anchor w \
1097 -justify left \
1098 -font [concat $mainfont bold]
1099 text $w.m.t \
1100 -background white -borderwidth 1 \
1101 -relief sunken \
1102 -width 80 -height 10 \
1103 -font $difffont \
1104 -yscrollcommand [list $w.m.sby set]
1105 label $w.m.l2 \
1106 -text {You must correct the above errors before committing.} \
1107 -anchor w \
1108 -justify left \
1109 -font [concat $mainfont bold]
1110 scrollbar $w.m.sby -command [list $w.m.t yview]
1111 pack $w.m.l1 -side top -fill x
1112 pack $w.m.l2 -side bottom -fill x
1113 pack $w.m.sby -side right -fill y
1114 pack $w.m.t -side left -fill both -expand 1
1115 pack $w.m -side top -fill both -expand 1 -padx 5 -pady 10
1116
1117 $w.m.t insert 1.0 $msg
1118 $w.m.t conf -state disabled
1119
1120 button $w.ok -text OK \
1121 -width 15 \
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001122 -font $mainfont \
Shawn O. Pearce6e27d822006-11-06 20:03:36 -05001123 -command "destroy $w"
1124 pack $w.ok -side bottom
1125
1126 bind $w <Visibility> "grab $w; focus $w"
1127 bind $w <Key-Return> "destroy $w"
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -05001128 wm title $w "$appname ([lindex [file split \
1129 [file normalize [file dirname $gitdir]]] \
1130 end]): error"
Shawn O. Pearce6e27d822006-11-06 20:03:36 -05001131 tkwait window $w
1132}
1133
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001134set next_console_id 0
1135
1136proc new_console {short_title long_title} {
Shawn O. Pearce37af79d2006-11-07 04:19:49 -05001137 global next_console_id console_data
1138 set w .console[incr next_console_id]
1139 set console_data($w) [list $short_title $long_title]
1140 return [console_init $w]
1141}
1142
1143proc console_init {w} {
1144 global console_cr console_data
Shawn O. Pearceee3dc932006-11-07 02:18:18 -05001145 global gitdir appname mainfont difffont
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001146
Shawn O. Pearceee3dc932006-11-07 02:18:18 -05001147 set console_cr($w) 1.0
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001148 toplevel $w
1149 frame $w.m
Shawn O. Pearce37af79d2006-11-07 04:19:49 -05001150 label $w.m.l1 -text "[lindex $console_data($w) 1]:" \
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001151 -anchor w \
1152 -justify left \
1153 -font [concat $mainfont bold]
1154 text $w.m.t \
1155 -background white -borderwidth 1 \
1156 -relief sunken \
1157 -width 80 -height 10 \
1158 -font $difffont \
1159 -state disabled \
1160 -yscrollcommand [list $w.m.sby set]
Shawn O. Pearce07123f42006-11-07 02:57:46 -05001161 label $w.m.s -anchor w \
1162 -justify left \
1163 -font [concat $mainfont bold]
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001164 scrollbar $w.m.sby -command [list $w.m.t yview]
1165 pack $w.m.l1 -side top -fill x
Shawn O. Pearce07123f42006-11-07 02:57:46 -05001166 pack $w.m.s -side bottom -fill x
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001167 pack $w.m.sby -side right -fill y
1168 pack $w.m.t -side left -fill both -expand 1
1169 pack $w.m -side top -fill both -expand 1 -padx 5 -pady 10
1170
Shawn O. Pearceee3dc932006-11-07 02:18:18 -05001171 button $w.ok -text {Running...} \
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001172 -width 15 \
1173 -font $mainfont \
1174 -state disabled \
1175 -command "destroy $w"
1176 pack $w.ok -side bottom
1177
1178 bind $w <Visibility> "focus $w"
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -05001179 wm title $w "$appname ([lindex [file split \
1180 [file normalize [file dirname $gitdir]]] \
1181 end]): [lindex $console_data($w) 0]"
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001182 return $w
1183}
1184
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -05001185proc console_exec {w cmd {after {}}} {
Shawn O. Pearcecc4b1c02006-11-06 23:47:05 -05001186 global tcl_platform
1187
1188 # -- Windows tosses the enviroment when we exec our child.
1189 # But most users need that so we have to relogin. :-(
1190 #
1191 if {$tcl_platform(platform) == {windows}} {
1192 set cmd [list sh --login -c "cd \"[pwd]\" && [join $cmd { }]"]
1193 }
1194
1195 # -- Tcl won't let us redirect both stdout and stderr to
1196 # the same pipe. So pass it through cat...
1197 #
1198 set cmd [concat | $cmd |& cat]
1199
1200 set fd_f [open $cmd r]
Shawn O. Pearceee3dc932006-11-07 02:18:18 -05001201 fconfigure $fd_f -blocking 0 -translation binary
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -05001202 fileevent $fd_f readable [list console_read $w $fd_f $after]
Shawn O. Pearcecc4b1c02006-11-06 23:47:05 -05001203}
1204
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -05001205proc console_read {w fd after} {
Shawn O. Pearce37af79d2006-11-07 04:19:49 -05001206 global console_cr console_data
Shawn O. Pearceee3dc932006-11-07 02:18:18 -05001207
Shawn O. Pearceee3dc932006-11-07 02:18:18 -05001208 set buf [read $fd]
Shawn O. Pearce37af79d2006-11-07 04:19:49 -05001209 if {$buf != {}} {
1210 if {![winfo exists $w]} {console_init $w}
1211 $w.m.t conf -state normal
1212 set c 0
1213 set n [string length $buf]
1214 while {$c < $n} {
1215 set cr [string first "\r" $buf $c]
1216 set lf [string first "\n" $buf $c]
1217 if {$cr < 0} {set cr [expr $n + 1]}
1218 if {$lf < 0} {set lf [expr $n + 1]}
Shawn O. Pearceee3dc932006-11-07 02:18:18 -05001219
Shawn O. Pearce37af79d2006-11-07 04:19:49 -05001220 if {$lf < $cr} {
1221 $w.m.t insert end [string range $buf $c $lf]
1222 set console_cr($w) [$w.m.t index {end -1c}]
1223 set c $lf
1224 incr c
1225 } else {
1226 $w.m.t delete $console_cr($w) end
1227 $w.m.t insert end "\n"
1228 $w.m.t insert end [string range $buf $c $cr]
1229 set c $cr
1230 incr c
1231 }
Shawn O. Pearceee3dc932006-11-07 02:18:18 -05001232 }
Shawn O. Pearce37af79d2006-11-07 04:19:49 -05001233 $w.m.t conf -state disabled
1234 $w.m.t see end
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001235 }
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001236
Shawn O. Pearce07123f42006-11-07 02:57:46 -05001237 fconfigure $fd -blocking 1
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001238 if {[eof $fd]} {
Shawn O. Pearce07123f42006-11-07 02:57:46 -05001239 if {[catch {close $fd}]} {
Shawn O. Pearce37af79d2006-11-07 04:19:49 -05001240 if {![winfo exists $w]} {console_init $w}
Shawn O. Pearce07123f42006-11-07 02:57:46 -05001241 $w.m.s conf -background red -text {Error: Command Failed}
Shawn O. Pearce37af79d2006-11-07 04:19:49 -05001242 $w.ok conf -text Close
1243 $w.ok conf -state normal
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -05001244 set ok 0
Shawn O. Pearce37af79d2006-11-07 04:19:49 -05001245 } elseif {[winfo exists $w]} {
Shawn O. Pearce07123f42006-11-07 02:57:46 -05001246 $w.m.s conf -background green -text {Success}
Shawn O. Pearce37af79d2006-11-07 04:19:49 -05001247 $w.ok conf -text Close
1248 $w.ok conf -state normal
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -05001249 set ok 1
Shawn O. Pearce07123f42006-11-07 02:57:46 -05001250 }
Shawn O. Pearceee3dc932006-11-07 02:18:18 -05001251 array unset console_cr $w
Shawn O. Pearce37af79d2006-11-07 04:19:49 -05001252 array unset console_data $w
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -05001253 if {$after != {}} {
1254 uplevel #0 $after $ok
1255 }
Shawn O. Pearce07123f42006-11-07 02:57:46 -05001256 return
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001257 }
Shawn O. Pearce07123f42006-11-07 02:57:46 -05001258 fconfigure $fd -blocking 0
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001259}
1260
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001261######################################################################
1262##
1263## ui commands
1264
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001265set starting_gitk_msg {Please wait... Starting gitk...}
Shawn O. Pearcecc4b1c02006-11-06 23:47:05 -05001266
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001267proc do_gitk {} {
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001268 global tcl_platform ui_status_value starting_gitk_msg
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001269
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001270 set ui_status_value $starting_gitk_msg
Shawn O. Pearcee57ca852006-11-06 21:34:10 -05001271 after 10000 {
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001272 if {$ui_status_value == $starting_gitk_msg} {
1273 set ui_status_value {Ready.}
1274 }
1275 }
1276
Shawn O. Pearcecc4b1c02006-11-06 23:47:05 -05001277 if {$tcl_platform(platform) == {windows}} {
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001278 exec sh -c gitk &
1279 } else {
1280 exec gitk &
1281 }
1282}
1283
1284proc do_quit {} {
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001285 global gitdir ui_comm
1286
1287 set save [file join $gitdir GITGUI_MSG]
Shawn O. Pearceec6b4242006-11-06 20:50:59 -05001288 set msg [string trim [$ui_comm get 0.0 end]]
1289 if {[$ui_comm edit modified] && $msg != {}} {
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001290 catch {
1291 set fd [open $save w]
1292 puts $fd [string trim [$ui_comm get 0.0 end]]
1293 close $fd
1294 }
Shawn O. Pearceec6b4242006-11-06 20:50:59 -05001295 } elseif {$msg == {} && [file exists $save]} {
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001296 file delete $save
1297 }
1298
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001299 destroy .
1300}
1301
1302proc do_rescan {} {
1303 update_status
1304}
1305
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001306proc do_checkin_all {} {
1307 global checkin_active ui_status_value
1308
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001309 if {$checkin_active || ![lock_index begin-update]} return
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001310
1311 set checkin_active 1
1312 set ui_status_value {Checking in all files...}
1313 after 1 {
1314 with_update_index {
1315 foreach path [array names file_states] {
1316 set s $file_states($path)
1317 set m [lindex $s 0]
1318 switch -- $m {
1319 AM -
1320 MM -
1321 _M -
1322 _D {toggle_mode $path}
1323 }
1324 }
1325 }
1326 set checkin_active 0
1327 set ui_status_value {Ready.}
1328 }
1329}
1330
1331proc do_signoff {} {
1332 global ui_comm
1333
1334 catch {
1335 set me [exec git var GIT_COMMITTER_IDENT]
1336 if {[regexp {(.*) [0-9]+ [-+0-9]+$} $me me name]} {
1337 set str "Signed-off-by: $name"
1338 if {[$ui_comm get {end -1c linestart} {end -1c}] != $str} {
1339 $ui_comm insert end "\n"
1340 $ui_comm insert end $str
1341 $ui_comm see end
1342 }
1343 }
1344 }
1345}
1346
Shawn O. Pearcee57ca852006-11-06 21:34:10 -05001347proc do_amend_last {} {
1348 load_last_commit
1349}
1350
Shawn O. Pearce6e27d822006-11-06 20:03:36 -05001351proc do_commit {} {
Shawn O. Pearceec6b4242006-11-06 20:50:59 -05001352 commit_tree
Shawn O. Pearce6e27d822006-11-06 20:03:36 -05001353}
1354
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001355# shift == 1: left click
1356# 3: right click
1357proc click {w x y shift wx wy} {
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001358 global ui_index ui_other
1359
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001360 set pos [split [$w index @$x,$y] .]
1361 set lno [lindex $pos 0]
1362 set col [lindex $pos 1]
1363 set path [$w get $lno.1 $lno.end]
1364 if {$path == {}} return
1365
1366 if {$col > 0 && $shift == 1} {
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001367 $ui_index tag remove in_diff 0.0 end
1368 $ui_other tag remove in_diff 0.0 end
1369 $w tag add in_diff $lno.0 [expr $lno + 1].0
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001370 show_diff $path
1371 }
1372}
1373
1374proc unclick {w x y} {
1375 set pos [split [$w index @$x,$y] .]
1376 set lno [lindex $pos 0]
1377 set col [lindex $pos 1]
1378 set path [$w get $lno.1 $lno.end]
1379 if {$path == {}} return
1380
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001381 if {$col == 0} {
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001382 toggle_mode $path
1383 }
1384}
1385
1386######################################################################
1387##
1388## ui init
1389
1390set mainfont {Helvetica 10}
1391set difffont {Courier 10}
1392set maincursor [. cget -cursor]
1393
Shawn O. Pearce66144892006-11-07 00:53:39 -05001394switch -glob -- "$tcl_platform(platform),$tcl_platform(os)" {
1395windows,* {set M1B Control; set M1T Ctrl}
1396unix,Darwin {set M1B M1; set M1T Cmd}
1397default {set M1B M1; set M1T M1}
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001398}
1399
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001400# -- Menu Bar
1401menu .mbar -tearoff 0
1402.mbar add cascade -label Project -menu .mbar.project
1403.mbar add cascade -label Commit -menu .mbar.commit
1404.mbar add cascade -label Fetch -menu .mbar.fetch
1405.mbar add cascade -label Pull -menu .mbar.pull
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001406.mbar add cascade -label Push -menu .mbar.push
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001407. configure -menu .mbar
1408
1409# -- Project Menu
1410menu .mbar.project
Shawn O. Pearce6f6eed22006-11-06 18:22:19 -05001411.mbar.project add command -label Visualize \
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001412 -command do_gitk \
1413 -font $mainfont
1414.mbar.project add command -label Quit \
1415 -command do_quit \
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001416 -accelerator $M1T-Q \
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001417 -font $mainfont
1418
1419# -- Commit Menu
1420menu .mbar.commit
1421.mbar.commit add command -label Rescan \
1422 -command do_rescan \
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001423 -accelerator F5 \
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001424 -font $mainfont
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001425lappend disable_on_lock \
1426 [list .mbar.commit entryconf [.mbar.commit index last] -state]
Shawn O. Pearcee57ca852006-11-06 21:34:10 -05001427.mbar.commit add command -label {Amend Last Commit} \
1428 -command do_amend_last \
1429 -font $mainfont
1430lappend disable_on_lock \
1431 [list .mbar.commit entryconf [.mbar.commit index last] -state]
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001432.mbar.commit add command -label {Check-in All Files} \
1433 -command do_checkin_all \
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001434 -accelerator $M1T-U \
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001435 -font $mainfont
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001436lappend disable_on_lock \
1437 [list .mbar.commit entryconf [.mbar.commit index last] -state]
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001438.mbar.commit add command -label {Sign Off} \
1439 -command do_signoff \
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001440 -accelerator $M1T-S \
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001441 -font $mainfont
1442.mbar.commit add command -label Commit \
1443 -command do_commit \
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001444 -accelerator $M1T-Return \
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001445 -font $mainfont
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001446lappend disable_on_lock \
1447 [list .mbar.commit entryconf [.mbar.commit index last] -state]
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001448
1449# -- Fetch Menu
1450menu .mbar.fetch
1451
1452# -- Pull Menu
1453menu .mbar.pull
1454
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001455# -- Push Menu
1456menu .mbar.push
1457
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001458# -- Main Window Layout
1459panedwindow .vpane -orient vertical
1460panedwindow .vpane.files -orient horizontal
Shawn O. Pearce6f6eed22006-11-06 18:22:19 -05001461.vpane add .vpane.files -sticky nsew -height 100 -width 400
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001462pack .vpane -anchor n -side top -fill both -expand 1
1463
1464# -- Index File List
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001465frame .vpane.files.index -height 100 -width 400
1466label .vpane.files.index.title -text {Modified Files} \
1467 -background green \
1468 -font $mainfont
1469text $ui_index -background white -borderwidth 0 \
1470 -width 40 -height 10 \
1471 -font $mainfont \
1472 -yscrollcommand {.vpane.files.index.sb set} \
1473 -cursor $maincursor \
1474 -state disabled
1475scrollbar .vpane.files.index.sb -command [list $ui_index yview]
1476pack .vpane.files.index.title -side top -fill x
1477pack .vpane.files.index.sb -side right -fill y
1478pack $ui_index -side left -fill both -expand 1
1479.vpane.files add .vpane.files.index -sticky nsew
1480
1481# -- Other (Add) File List
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001482frame .vpane.files.other -height 100 -width 100
1483label .vpane.files.other.title -text {Untracked Files} \
1484 -background red \
1485 -font $mainfont
1486text $ui_other -background white -borderwidth 0 \
1487 -width 40 -height 10 \
1488 -font $mainfont \
1489 -yscrollcommand {.vpane.files.other.sb set} \
1490 -cursor $maincursor \
1491 -state disabled
1492scrollbar .vpane.files.other.sb -command [list $ui_other yview]
1493pack .vpane.files.other.title -side top -fill x
1494pack .vpane.files.other.sb -side right -fill y
1495pack $ui_other -side left -fill both -expand 1
1496.vpane.files add .vpane.files.other -sticky nsew
1497
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001498$ui_index tag conf in_diff -font [concat $mainfont bold]
1499$ui_other tag conf in_diff -font [concat $mainfont bold]
1500
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001501# -- Diff Header
1502set ui_fname_value {}
1503set ui_fstatus_value {}
Shawn O. Pearce6f6eed22006-11-06 18:22:19 -05001504frame .vpane.diff -height 200 -width 400
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001505frame .vpane.diff.header
1506label .vpane.diff.header.l1 -text {File:} -font $mainfont
1507label .vpane.diff.header.l2 -textvariable ui_fname_value \
1508 -anchor w \
1509 -justify left \
1510 -font $mainfont
1511label .vpane.diff.header.l3 -text {Status:} -font $mainfont
1512label .vpane.diff.header.l4 -textvariable ui_fstatus_value \
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001513 -width $max_status_desc \
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001514 -anchor w \
1515 -justify left \
1516 -font $mainfont
1517pack .vpane.diff.header.l1 -side left
1518pack .vpane.diff.header.l2 -side left -fill x
1519pack .vpane.diff.header.l4 -side right
1520pack .vpane.diff.header.l3 -side right
1521
1522# -- Diff Body
1523frame .vpane.diff.body
1524set ui_diff .vpane.diff.body.t
1525text $ui_diff -background white -borderwidth 0 \
Shawn O. Pearce6f6eed22006-11-06 18:22:19 -05001526 -width 80 -height 15 -wrap none \
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001527 -font $difffont \
1528 -xscrollcommand {.vpane.diff.body.sbx set} \
1529 -yscrollcommand {.vpane.diff.body.sby set} \
1530 -cursor $maincursor \
1531 -state disabled
1532scrollbar .vpane.diff.body.sbx -orient horizontal \
1533 -command [list $ui_diff xview]
1534scrollbar .vpane.diff.body.sby -orient vertical \
1535 -command [list $ui_diff yview]
1536pack .vpane.diff.body.sbx -side bottom -fill x
1537pack .vpane.diff.body.sby -side right -fill y
1538pack $ui_diff -side left -fill both -expand 1
1539pack .vpane.diff.header -side top -fill x
1540pack .vpane.diff.body -side bottom -fill both -expand 1
1541.vpane add .vpane.diff -stick nsew
1542
1543$ui_diff tag conf dm -foreground red
1544$ui_diff tag conf dp -foreground blue
1545$ui_diff tag conf da -font [concat $difffont bold]
1546$ui_diff tag conf di -foreground "#00a000"
1547$ui_diff tag conf dni -foreground "#a000a0"
1548$ui_diff tag conf bold -font [concat $difffont bold]
1549
1550# -- Commit Area
Shawn O. Pearcee57ca852006-11-06 21:34:10 -05001551frame .vpane.commarea -height 170
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001552.vpane add .vpane.commarea -stick nsew
1553
1554# -- Commit Area Buttons
1555frame .vpane.commarea.buttons
1556label .vpane.commarea.buttons.l -text {} \
1557 -anchor w \
1558 -justify left \
1559 -font $mainfont
1560pack .vpane.commarea.buttons.l -side top -fill x
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001561pack .vpane.commarea.buttons -side left -fill y
1562
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001563button .vpane.commarea.buttons.rescan -text {Rescan} \
1564 -command do_rescan \
1565 -font $mainfont
1566pack .vpane.commarea.buttons.rescan -side top -fill x
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001567lappend disable_on_lock {.vpane.commarea.buttons.rescan conf -state}
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001568
Shawn O. Pearcee57ca852006-11-06 21:34:10 -05001569button .vpane.commarea.buttons.amend -text {Amend Last} \
1570 -command do_amend_last \
1571 -font $mainfont
1572pack .vpane.commarea.buttons.amend -side top -fill x
1573lappend disable_on_lock {.vpane.commarea.buttons.amend conf -state}
1574
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001575button .vpane.commarea.buttons.ciall -text {Check-in All} \
1576 -command do_checkin_all \
1577 -font $mainfont
1578pack .vpane.commarea.buttons.ciall -side top -fill x
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001579lappend disable_on_lock {.vpane.commarea.buttons.ciall conf -state}
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001580
1581button .vpane.commarea.buttons.signoff -text {Sign Off} \
1582 -command do_signoff \
1583 -font $mainfont
1584pack .vpane.commarea.buttons.signoff -side top -fill x
1585
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001586button .vpane.commarea.buttons.commit -text {Commit} \
1587 -command do_commit \
1588 -font $mainfont
1589pack .vpane.commarea.buttons.commit -side top -fill x
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001590lappend disable_on_lock {.vpane.commarea.buttons.commit conf -state}
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001591
1592# -- Commit Message Buffer
1593frame .vpane.commarea.buffer
1594set ui_comm .vpane.commarea.buffer.t
Shawn O. Pearcebd1e2b42006-11-06 22:03:05 -05001595set ui_coml .vpane.commarea.buffer.l
1596label $ui_coml -text {Commit Message:} \
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001597 -anchor w \
1598 -justify left \
1599 -font $mainfont
Shawn O. Pearcebd1e2b42006-11-06 22:03:05 -05001600trace add variable commit_type write {uplevel #0 {
1601 switch -glob $commit_type \
1602 initial {$ui_coml conf -text {Initial Commit Message:}} \
1603 amend {$ui_coml conf -text {Amended Commit Message:}} \
1604 merge {$ui_coml conf -text {Merge Commit Message:}} \
1605 * {$ui_coml conf -text {Commit Message:}}
1606}}
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001607text $ui_comm -background white -borderwidth 1 \
1608 -relief sunken \
1609 -width 75 -height 10 -wrap none \
1610 -font $difffont \
1611 -yscrollcommand {.vpane.commarea.buffer.sby set} \
1612 -cursor $maincursor
1613scrollbar .vpane.commarea.buffer.sby -command [list $ui_comm yview]
Shawn O. Pearcebd1e2b42006-11-06 22:03:05 -05001614pack $ui_coml -side top -fill x
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001615pack .vpane.commarea.buffer.sby -side right -fill y
1616pack $ui_comm -side left -fill y
1617pack .vpane.commarea.buffer -side left -fill y
1618
1619# -- Status Bar
1620set ui_status_value {Initializing...}
1621label .status -textvariable ui_status_value \
1622 -anchor w \
1623 -justify left \
1624 -borderwidth 1 \
1625 -relief sunken \
1626 -font $mainfont
1627pack .status -anchor w -side bottom -fill x
1628
1629# -- Key Bindings
Shawn O. Pearceec6b4242006-11-06 20:50:59 -05001630bind $ui_comm <$M1B-Key-Return> {do_commit;break}
Shawn O. Pearce07123f42006-11-07 02:57:46 -05001631bind . <Destroy> do_quit
1632bind all <Key-F5> do_rescan
1633bind all <$M1B-Key-r> do_rescan
1634bind all <$M1B-Key-R> do_rescan
1635bind . <$M1B-Key-s> do_signoff
1636bind . <$M1B-Key-S> do_signoff
1637bind . <$M1B-Key-u> do_checkin_all
1638bind . <$M1B-Key-U> do_checkin_all
1639bind . <$M1B-Key-Return> do_commit
1640bind all <$M1B-Key-q> do_quit
1641bind all <$M1B-Key-Q> do_quit
1642bind all <$M1B-Key-w> {destroy [winfo toplevel %W]}
1643bind all <$M1B-Key-W> {destroy [winfo toplevel %W]}
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001644foreach i [list $ui_index $ui_other] {
1645 bind $i <Button-1> {click %W %x %y 1 %X %Y; break}
1646 bind $i <Button-3> {click %W %x %y 3 %X %Y; break}
1647 bind $i <ButtonRelease-1> {unclick %W %x %y; break}
1648}
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001649unset i M1B M1T
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001650
1651######################################################################
1652##
1653## main
1654
Shawn O. Pearceb8ce6f02006-11-07 00:20:56 -05001655set appname [lindex [file split $argv0] end]
1656set gitdir {}
1657
1658if {[catch {set cdup [exec git rev-parse --show-cdup]} err]} {
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001659 show_msg {} . "Cannot find the git directory: $err"
1660 exit 1
1661}
Shawn O. Pearcebd1e2b42006-11-06 22:03:05 -05001662if {$cdup != ""} {
1663 cd $cdup
1664}
1665unset cdup
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001666
Shawn O. Pearceb8ce6f02006-11-07 00:20:56 -05001667if {[catch {set gitdir [exec git rev-parse --git-dir]} err]} {
1668 show_msg {} . "Cannot find the git directory: $err"
1669 exit 1
1670}
1671
Shawn O. Pearceec6b4242006-11-06 20:50:59 -05001672if {$appname == {git-citool}} {
1673 set single_commit 1
1674}
1675
1676wm title . "$appname ([file normalize [file dirname $gitdir]])"
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001677focus -force $ui_comm
Shawn O. Pearce0d4f3eb2006-11-07 04:26:02 -05001678load_repo_config
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001679load_all_remotes
1680populate_remote_menu .mbar.fetch From fetch_from
1681populate_remote_menu .mbar.push To push_to
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -05001682populate_pull_menu .mbar.pull
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001683update_status