blob: 4aa035a6c4536d266f21ec41d131ecbd9651fe6f [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. Pearcecb07fc22006-11-06 14:20:27 -050073 global status_active file_states
74
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. Pearcecb07fc22006-11-06 14:20:27 -050087 array unset file_states
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -050088 foreach w [list $ui_index $ui_other] {
89 $w conf -state normal
90 $w delete 0.0 end
91 $w conf -state disabled
92 }
93
Shawn O. Pearce131f5032006-11-06 16:07:32 -050094 if {![$ui_comm edit modified]
Shawn O. Pearcecc4b1c02006-11-06 23:47:05 -050095 || [string trim [$ui_comm get 0.0 end]] == {}} {
Shawn O. Pearce131f5032006-11-06 16:07:32 -050096 if {[load_message GITGUI_MSG]} {
97 } elseif {[load_message MERGE_MSG]} {
98 } elseif {[load_message SQUASH_MSG]} {
99 }
100 $ui_comm edit modified false
101 }
102
103 set status_active 1
104 set ui_status_value {Refreshing file status...}
105 set fd_rf [open "| git update-index -q --unmerged --refresh" r]
106 fconfigure $fd_rf -blocking 0 -translation binary
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500107 fileevent $fd_rf readable [list read_refresh $fd_rf $final]
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500108}
109
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500110proc read_refresh {fd final} {
111 global gitdir PARENT commit_type
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500112 global ui_index ui_other ui_status_value ui_comm
113 global status_active file_states
114
115 read $fd
116 if {![eof $fd]} return
117 close $fd
118
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500119 set ls_others [list | git ls-files --others -z \
120 --exclude-per-directory=.gitignore]
121 set info_exclude [file join $gitdir info exclude]
122 if {[file readable $info_exclude]} {
123 lappend ls_others "--exclude-from=$info_exclude"
124 }
125
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500126 set status_active 3
127 set ui_status_value {Scanning for modified files ...}
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500128 set fd_di [open "| git diff-index --cached -z $PARENT" r]
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500129 set fd_df [open "| git diff-files -z" r]
130 set fd_lo [open $ls_others r]
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500131
132 fconfigure $fd_di -blocking 0 -translation binary
133 fconfigure $fd_df -blocking 0 -translation binary
134 fconfigure $fd_lo -blocking 0 -translation binary
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500135 fileevent $fd_di readable [list read_diff_index $fd_di $final]
136 fileevent $fd_df readable [list read_diff_files $fd_df $final]
137 fileevent $fd_lo readable [list read_ls_others $fd_lo $final]
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500138}
139
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500140proc load_message {file} {
141 global gitdir ui_comm
142
143 set f [file join $gitdir $file]
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500144 if {[file isfile $f]} {
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500145 if {[catch {set fd [open $f r]}]} {
146 return 0
147 }
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500148 set content [string trim [read $fd]]
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500149 close $fd
150 $ui_comm delete 0.0 end
151 $ui_comm insert end $content
152 return 1
153 }
154 return 0
155}
156
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500157proc read_diff_index {fd final} {
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500158 global buf_rdi
159
160 append buf_rdi [read $fd]
161 set pck [split $buf_rdi "\0"]
162 set buf_rdi [lindex $pck end]
163 foreach {m p} [lrange $pck 0 end-1] {
164 if {$m != {} && $p != {}} {
165 display_file $p [string index $m end]_
166 }
167 }
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500168 status_eof $fd buf_rdi $final
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500169}
170
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500171proc read_diff_files {fd final} {
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500172 global buf_rdf
173
174 append buf_rdf [read $fd]
175 set pck [split $buf_rdf "\0"]
176 set buf_rdf [lindex $pck end]
177 foreach {m p} [lrange $pck 0 end-1] {
178 if {$m != {} && $p != {}} {
179 display_file $p _[string index $m end]
180 }
181 }
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500182 status_eof $fd buf_rdf $final
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500183}
184
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500185proc read_ls_others {fd final} {
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500186 global buf_rlo
187
188 append buf_rlo [read $fd]
189 set pck [split $buf_rlo "\0"]
190 set buf_rlo [lindex $pck end]
191 foreach p [lrange $pck 0 end-1] {
192 display_file $p _O
193 }
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500194 status_eof $fd buf_rlo $final
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500195}
196
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500197proc status_eof {fd buf final} {
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500198 global status_active $buf
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500199 global ui_fname_value ui_status_value file_states
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500200
201 if {[eof $fd]} {
202 set $buf {}
203 close $fd
204 if {[incr status_active -1] == 0} {
Shawn O. Pearcee210e672006-11-06 19:12:58 -0500205 unlock_index
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500206
207 set ui_status_value $final
208 if {$ui_fname_value != {} && [array names file_states \
209 -exact $ui_fname_value] != {}} {
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500210 show_diff $ui_fname_value
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500211 } else {
212 clear_diff
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500213 }
214 }
215 }
216}
217
218######################################################################
219##
220## diff
221
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500222proc clear_diff {} {
223 global ui_diff ui_fname_value ui_fstatus_value
224
225 $ui_diff conf -state normal
226 $ui_diff delete 0.0 end
227 $ui_diff conf -state disabled
228 set ui_fname_value {}
229 set ui_fstatus_value {}
230}
231
232proc show_diff {path} {
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500233 global file_states PARENT diff_3way diff_active
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500234 global ui_diff ui_fname_value ui_fstatus_value ui_status_value
235
Shawn O. Pearcee210e672006-11-06 19:12:58 -0500236 if {$diff_active || ![lock_index read]} return
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500237
238 clear_diff
239 set s $file_states($path)
240 set m [lindex $s 0]
241 set diff_3way 0
242 set diff_active 1
243 set ui_fname_value $path
244 set ui_fstatus_value [mapdesc $m $path]
245 set ui_status_value "Loading diff of $path..."
246
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500247 set cmd [list | git diff-index -p $PARENT -- $path]
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500248 switch $m {
249 AM {
250 }
251 MM {
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500252 set cmd [list | git diff-index -p -c $PARENT $path]
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500253 }
254 _O {
255 if {[catch {
256 set fd [open $path r]
257 set content [read $fd]
258 close $fd
259 } err ]} {
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500260 set diff_active 0
Shawn O. Pearcee210e672006-11-06 19:12:58 -0500261 unlock_index
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500262 set ui_status_value "Unable to display $path"
263 error_popup "Error loading file:\n$err"
264 return
265 }
266 $ui_diff conf -state normal
267 $ui_diff insert end $content
268 $ui_diff conf -state disabled
Shawn O. Pearcebd1e2b42006-11-06 22:03:05 -0500269 set diff_active 0
270 unlock_index
271 set ui_status_value {Ready.}
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500272 return
273 }
274 }
275
276 if {[catch {set fd [open $cmd r]} err]} {
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500277 set diff_active 0
Shawn O. Pearcee210e672006-11-06 19:12:58 -0500278 unlock_index
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500279 set ui_status_value "Unable to display $path"
280 error_popup "Error loading diff:\n$err"
281 return
282 }
283
Shawn O. Pearce6f6eed22006-11-06 18:22:19 -0500284 fconfigure $fd -blocking 0 -translation auto
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500285 fileevent $fd readable [list read_diff $fd]
286}
287
288proc read_diff {fd} {
289 global ui_diff ui_status_value diff_3way diff_active
290
291 while {[gets $fd line] >= 0} {
Shawn O. Pearce6f6eed22006-11-06 18:22:19 -0500292 if {[string match {diff --git *} $line]} continue
293 if {[string match {diff --combined *} $line]} continue
294 if {[string match {--- *} $line]} continue
295 if {[string match {+++ *} $line]} continue
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500296 if {[string match index* $line]} {
297 if {[string first , $line] >= 0} {
298 set diff_3way 1
299 }
300 }
301
302 $ui_diff conf -state normal
303 if {!$diff_3way} {
304 set x [string index $line 0]
305 switch -- $x {
306 "@" {set tags da}
307 "+" {set tags dp}
308 "-" {set tags dm}
309 default {set tags {}}
310 }
311 } else {
312 set x [string range $line 0 1]
313 switch -- $x {
314 default {set tags {}}
315 "@@" {set tags da}
316 "++" {set tags dp; set x " +"}
317 " +" {set tags {di bold}; set x "++"}
318 "+ " {set tags dni; set x "-+"}
319 "--" {set tags dm; set x " -"}
320 " -" {set tags {dm bold}; set x "--"}
321 "- " {set tags di; set x "+-"}
322 default {set tags {}}
323 }
324 set line [string replace $line 0 1 $x]
325 }
326 $ui_diff insert end $line $tags
327 $ui_diff insert end "\n"
328 $ui_diff conf -state disabled
329 }
330
331 if {[eof $fd]} {
332 close $fd
333 set diff_active 0
Shawn O. Pearcee210e672006-11-06 19:12:58 -0500334 unlock_index
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500335 set ui_status_value {Ready.}
336 }
337}
338
339######################################################################
340##
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500341## commit
342
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500343proc load_last_commit {} {
344 global HEAD PARENT commit_type ui_comm
345
346 if {$commit_type == {amend}} return
347 if {$commit_type != {normal}} {
348 error_popup "Can't amend a $commit_type commit."
349 return
350 }
351
352 set msg {}
353 set parent {}
354 set parent_count 0
355 if {[catch {
356 set fd [open "| git cat-file commit $HEAD" r]
357 while {[gets $fd line] > 0} {
358 if {[string match {parent *} $line]} {
359 set parent [string range $line 7 end]
360 incr parent_count
361 }
362 }
363 set msg [string trim [read $fd]]
364 close $fd
365 } err]} {
366 error_popup "Error loading commit data for amend:\n$err"
367 return
368 }
369
370 if {$parent_count == 0} {
371 set commit_type amend
372 set HEAD {}
373 set PARENT {}
374 update_status
375 } elseif {$parent_count == 1} {
376 set commit_type amend
377 set PARENT $parent
378 $ui_comm delete 0.0 end
379 $ui_comm insert end $msg
380 $ui_comm edit modified false
381 update_status
382 } else {
383 error_popup {You can't amend a merge commit.}
384 return
385 }
386}
387
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500388proc commit_tree {} {
389 global tcl_platform HEAD gitdir commit_type file_states
390 global commit_active ui_status_value
391 global ui_comm
392
393 if {$commit_active || ![lock_index update]} return
394
395 # -- Our in memory state should match the repository.
396 #
397 repository_state curHEAD cur_type
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500398 if {$commit_type == {amend}
399 && $cur_type == {normal}
400 && $curHEAD == $HEAD} {
401 } elseif {$commit_type != $cur_type || $HEAD != $curHEAD} {
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500402 error_popup {Last scanned state does not match repository state.
403
404Its highly likely that another Git program modified the
405repository since our last scan. A rescan is required
406before committing.
407}
408 unlock_index
409 update_status
410 return
411 }
412
413 # -- At least one file should differ in the index.
414 #
415 set files_ready 0
416 foreach path [array names file_states] {
417 set s $file_states($path)
418 switch -glob -- [lindex $s 0] {
419 _* {continue}
420 A* -
421 D* -
422 M* {set files_ready 1; break}
423 U* {
424 error_popup "Unmerged files cannot be committed.
425
426File $path has merge conflicts.
427You must resolve them and check the file in before committing.
428"
429 unlock_index
430 return
431 }
432 default {
433 error_popup "Unknown file state [lindex $s 0] detected.
434
435File $path cannot be committed by this program.
436"
437 }
438 }
439 }
440 if {!$files_ready} {
441 error_popup {No checked-in files to commit.
442
443You must check-in at least 1 file before you can commit.
444}
445 unlock_index
446 return
447 }
448
449 # -- A message is required.
450 #
451 set msg [string trim [$ui_comm get 1.0 end]]
452 if {$msg == {}} {
453 error_popup {Please supply a commit message.
454
455A good commit message has the following format:
456
457- First line: Describe in one sentance what you did.
458- Second line: Blank
459- Remaining lines: Describe why this change is good.
460}
461 unlock_index
462 return
463 }
464
465 # -- Ask the pre-commit hook for the go-ahead.
466 #
467 set pchook [file join $gitdir hooks pre-commit]
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500468 if {$tcl_platform(platform) == {windows} && [file isfile $pchook]} {
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500469 set pchook [list sh -c \
470 "if test -x \"$pchook\"; then exec \"$pchook\"; fi"]
471 } elseif {[file executable $pchook]} {
472 set pchook [list $pchook]
473 } else {
474 set pchook {}
475 }
476 if {$pchook != {} && [catch {eval exec $pchook} err]} {
477 hook_failed_popup pre-commit $err
478 unlock_index
479 return
480 }
481
482 # -- Write the tree in the background.
483 #
484 set commit_active 1
485 set ui_status_value {Committing changes...}
486
487 set fd_wt [open "| git write-tree" r]
Shawn O. Pearcebd1e2b42006-11-06 22:03:05 -0500488 fileevent $fd_wt readable [list commit_stage2 $fd_wt $curHEAD $msg]
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500489}
490
491proc commit_stage2 {fd_wt curHEAD msg} {
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500492 global single_commit gitdir PARENT commit_type
493 global commit_active ui_status_value ui_comm
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500494
495 gets $fd_wt tree_id
496 close $fd_wt
497
498 if {$tree_id == {}} {
499 error_popup "write-tree failed"
500 set commit_active 0
501 set ui_status_value {Commit failed.}
502 unlock_index
503 return
504 }
505
506 # -- Create the commit.
507 #
508 set cmd [list git commit-tree $tree_id]
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500509 if {$PARENT != {}} {
510 lappend cmd -p $PARENT
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500511 }
512 if {$commit_type == {merge}} {
513 if {[catch {
514 set fd_mh [open [file join $gitdir MERGE_HEAD] r]
Shawn O. Pearcebd1e2b42006-11-06 22:03:05 -0500515 while {[gets $fd_mh merge_head] >= 0} {
516 lappend cmd -p $merge_head
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500517 }
518 close $fd_mh
519 } err]} {
520 error_popup "Loading MERGE_HEADs failed:\n$err"
521 set commit_active 0
522 set ui_status_value {Commit failed.}
523 unlock_index
524 return
525 }
526 }
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500527 if {$PARENT == {}} {
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500528 # git commit-tree writes to stderr during initial commit.
529 lappend cmd 2>/dev/null
530 }
531 lappend cmd << $msg
532 if {[catch {set cmt_id [eval exec $cmd]} err]} {
533 error_popup "commit-tree failed:\n$err"
534 set commit_active 0
535 set ui_status_value {Commit failed.}
536 unlock_index
537 return
538 }
539
540 # -- Update the HEAD ref.
541 #
542 set reflogm commit
543 if {$commit_type != {normal}} {
544 append reflogm " ($commit_type)"
545 }
546 set i [string first "\n" $msg]
547 if {$i >= 0} {
548 append reflogm {: } [string range $msg 0 [expr $i - 1]]
549 } else {
550 append reflogm {: } $msg
551 }
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500552 set cmd [list git update-ref -m $reflogm HEAD $cmt_id $curHEAD]
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500553 if {[catch {eval exec $cmd} err]} {
554 error_popup "update-ref failed:\n$err"
555 set commit_active 0
556 set ui_status_value {Commit failed.}
557 unlock_index
558 return
559 }
560
561 # -- Cleanup after ourselves.
562 #
563 catch {file delete [file join $gitdir MERGE_HEAD]}
564 catch {file delete [file join $gitdir MERGE_MSG]}
565 catch {file delete [file join $gitdir SQUASH_MSG]}
566 catch {file delete [file join $gitdir GITGUI_MSG]}
567
568 # -- Let rerere do its thing.
569 #
570 if {[file isdirectory [file join $gitdir rr-cache]]} {
571 catch {exec git rerere}
572 }
573
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500574 $ui_comm delete 0.0 end
575 $ui_comm edit modified false
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500576
577 if {$single_commit} do_quit
578
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500579 set commit_type {}
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500580 set commit_active 0
Shawn O. Pearcebd1e2b42006-11-06 22:03:05 -0500581 set HEAD $cmt_id
582 set PARENT $cmt_id
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500583 unlock_index
Shawn O. Pearcee57ca852006-11-06 21:34:10 -0500584 update_status "Changes committed as $cmt_id."
Shawn O. Pearceec6b4242006-11-06 20:50:59 -0500585}
586
587######################################################################
588##
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500589## fetch pull push
590
591proc fetch_from {remote} {
592 set w [new_console "fetch $remote" \
593 "Fetching new changes from $remote"]
Shawn O. Pearcecc4b1c02006-11-06 23:47:05 -0500594 set cmd [list git fetch]
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500595 lappend cmd $remote
Shawn O. Pearcecc4b1c02006-11-06 23:47:05 -0500596 console_exec $w $cmd
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500597}
598
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -0500599proc pull_remote {remote branch} {
600 set w [new_console "pull $remote $branch" \
601 "Pulling new changes from branch $branch in $remote"]
602 set cmd [list git pull]
603 lappend cmd $remote
604 lappend cmd $branch
605 console_exec $w $cmd [list post_pull_remote $remote $branch]
606}
607
608proc post_pull_remote {remote branch success} {
609 if {$success} {
610 update_status "Successfully pulled $branch from $remote."
611 } else {
612 update_status "Conflicts detected while pulling $branch from $remote."
613 }
614}
615
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500616proc push_to {remote} {
617 set w [new_console "push $remote" \
618 "Pushing changes to $remote"]
Shawn O. Pearcecc4b1c02006-11-06 23:47:05 -0500619 set cmd [list git push]
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500620 lappend cmd $remote
Shawn O. Pearcecc4b1c02006-11-06 23:47:05 -0500621 console_exec $w $cmd
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500622}
623
624######################################################################
625##
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500626## ui helpers
627
628proc mapcol {state path} {
629 global all_cols
630
631 if {[catch {set r $all_cols($state)}]} {
632 puts "error: no column for state={$state} $path"
633 return o
634 }
635 return $r
636}
637
638proc mapicon {state path} {
639 global all_icons
640
641 if {[catch {set r $all_icons($state)}]} {
642 puts "error: no icon for state={$state} $path"
643 return file_plain
644 }
645 return $r
646}
647
648proc mapdesc {state path} {
649 global all_descs
650
651 if {[catch {set r $all_descs($state)}]} {
652 puts "error: no desc for state={$state} $path"
653 return $state
654 }
655 return $r
656}
657
658proc bsearch {w path} {
659 set hi [expr [lindex [split [$w index end] .] 0] - 2]
660 if {$hi == 0} {
661 return -1
662 }
663 set lo 0
664 while {$lo < $hi} {
665 set mi [expr [expr $lo + $hi] / 2]
666 set ti [expr $mi + 1]
667 set cmp [string compare [$w get $ti.1 $ti.end] $path]
668 if {$cmp < 0} {
669 set lo $ti
670 } elseif {$cmp == 0} {
671 return $mi
672 } else {
673 set hi $mi
674 }
675 }
676 return -[expr $lo + 1]
677}
678
679proc merge_state {path state} {
680 global file_states
681
682 if {[array names file_states -exact $path] == {}} {
683 set o __
684 set s [list $o none none]
685 } else {
686 set s $file_states($path)
687 set o [lindex $s 0]
688 }
689
690 set m [lindex $s 0]
691 if {[string index $state 0] == "_"} {
692 set state [string index $m 0][string index $state 1]
693 } elseif {[string index $state 0] == "*"} {
694 set state _[string index $state 1]
695 }
696
697 if {[string index $state 1] == "_"} {
698 set state [string index $state 0][string index $m 1]
699 } elseif {[string index $state 1] == "*"} {
700 set state [string index $state 0]_
701 }
702
703 set file_states($path) [lreplace $s 0 0 $state]
704 return $o
705}
706
707proc display_file {path state} {
708 global ui_index ui_other file_states
709
710 set old_m [merge_state $path $state]
711 set s $file_states($path)
712 set m [lindex $s 0]
713
714 if {[mapcol $m $path] == "o"} {
715 set ii 1
716 set ai 2
717 set iw $ui_index
718 set aw $ui_other
719 } else {
720 set ii 2
721 set ai 1
722 set iw $ui_other
723 set aw $ui_index
724 }
725
726 set d [lindex $s $ii]
727 if {$d != "none"} {
728 set lno [bsearch $iw $path]
729 if {$lno >= 0} {
730 incr lno
731 $iw conf -state normal
732 $iw delete $lno.0 [expr $lno + 1].0
733 $iw conf -state disabled
734 set s [lreplace $s $ii $ii none]
735 }
736 }
737
738 set d [lindex $s $ai]
739 if {$d == "none"} {
740 set lno [expr abs([bsearch $aw $path] + 1) + 1]
741 $aw conf -state normal
742 set ico [$aw image create $lno.0 \
743 -align center -padx 5 -pady 1 \
744 -image [mapicon $m $path]]
745 $aw insert $lno.1 "$path\n"
746 $aw conf -state disabled
747 set file_states($path) [lreplace $s $ai $ai [list $ico]]
748 } elseif {[mapicon $m $path] != [mapicon $old_m $path]} {
749 set ico [lindex $d 0]
750 $aw image conf $ico -image [mapicon $m $path]
751 }
752}
753
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500754proc with_update_index {body} {
755 global update_index_fd
756
757 if {$update_index_fd == {}} {
Shawn O. Pearcee210e672006-11-06 19:12:58 -0500758 if {![lock_index update]} return
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500759 set update_index_fd [open \
760 "| git update-index --add --remove -z --stdin" \
761 w]
762 fconfigure $update_index_fd -translation binary
763 uplevel 1 $body
764 close $update_index_fd
765 set update_index_fd {}
Shawn O. Pearcee210e672006-11-06 19:12:58 -0500766 unlock_index
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500767 } else {
768 uplevel 1 $body
769 }
770}
771
772proc update_index {path} {
773 global update_index_fd
774
775 if {$update_index_fd == {}} {
776 error {not in with_update_index}
777 } else {
778 puts -nonewline $update_index_fd "$path\0"
779 }
780}
781
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500782proc toggle_mode {path} {
Shawn O. Pearcebd1e2b42006-11-06 22:03:05 -0500783 global file_states ui_fname_value
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500784
785 set s $file_states($path)
786 set m [lindex $s 0]
787
788 switch -- $m {
789 AM -
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500790 _O {set new A*}
791 _M -
792 MM {set new M*}
Shawn O. Pearcebd1e2b42006-11-06 22:03:05 -0500793 AD -
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500794 _D {set new D*}
795 default {return}
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500796 }
797
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500798 with_update_index {update_index $path}
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500799 display_file $path $new
Shawn O. Pearcebd1e2b42006-11-06 22:03:05 -0500800 if {$ui_fname_value == $path} {
801 show_diff $path
802 }
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500803}
804
805######################################################################
806##
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500807## config (fetch push pull)
808
Shawn O. Pearce0d4f3eb2006-11-07 04:26:02 -0500809proc load_repo_config {} {
810 global repo_config
811
812 array unset repo_config
813 catch {
814 set fd_rc [open "| git repo-config --list" r]
815 while {[gets $fd_rc line] >= 0} {
816 if {[regexp {^([^=]+)=(.*)$} $line line name value]} {
817 lappend repo_config($name) $value
818 }
819 }
820 close $fd_rc
821 }
822}
823
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500824proc load_all_remotes {} {
Shawn O. Pearce0d4f3eb2006-11-07 04:26:02 -0500825 global gitdir all_remotes repo_config
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500826
827 set all_remotes [list]
828 set rm_dir [file join $gitdir remotes]
829 if {[file isdirectory $rm_dir]} {
Shawn O. Pearced47ae542006-11-07 03:00:20 -0500830 set all_remotes [concat $all_remotes [glob \
831 -types f \
832 -tails \
833 -nocomplain \
834 -directory $rm_dir *]]
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500835 }
836
Shawn O. Pearce0d4f3eb2006-11-07 04:26:02 -0500837 foreach line [array names repo_config remote.*.url] {
838 if {[regexp ^remote\.(.*)\.url\$ $line line name]} {
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500839 lappend all_remotes $name
840 }
841 }
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500842
843 set all_remotes [lsort -unique $all_remotes]
844}
845
846proc populate_remote_menu {m pfx op} {
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -0500847 global all_remotes mainfont
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500848
849 foreach remote $all_remotes {
850 $m add command -label "$pfx $remote..." \
851 -command [list $op $remote] \
852 -font $mainfont
853 }
854}
855
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -0500856proc populate_pull_menu {m} {
857 global gitdir repo_config all_remotes mainfont
858
859 foreach remote $all_remotes {
860 set rb {}
861 if {[array get repo_config remote.$remote.url] != {}} {
862 if {[array get repo_config remote.$remote.fetch] != {}} {
863 regexp {^([^:]+):} \
864 [lindex $repo_config(remote.$remote.fetch) 0] \
865 line rb
866 }
867 } else {
868 catch {
869 set fd [open [file join $gitdir remotes $remote] r]
870 while {[gets $fd line] >= 0} {
871 if {[regexp {^Pull:[ \t]*([^:]+):} $line line rb]} {
872 break
873 }
874 }
875 close $fd
876 }
877 }
878
879 set rb_short $rb
880 regsub ^refs/heads/ $rb {} rb_short
881 if {$rb_short != {}} {
882 $m add command \
883 -label "Branch $rb_short from $remote..." \
884 -command [list pull_remote $remote $rb] \
885 -font $mainfont
886 }
887 }
888}
889
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -0500890######################################################################
891##
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500892## icons
893
894set filemask {
895#define mask_width 14
896#define mask_height 15
897static unsigned char mask_bits[] = {
898 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f,
899 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f,
900 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f};
901}
902
903image create bitmap file_plain -background white -foreground black -data {
904#define plain_width 14
905#define plain_height 15
906static unsigned char plain_bits[] = {
907 0xfe, 0x01, 0x02, 0x03, 0x02, 0x05, 0x02, 0x09, 0x02, 0x1f, 0x02, 0x10,
908 0x02, 0x10, 0x02, 0x10, 0x02, 0x10, 0x02, 0x10, 0x02, 0x10, 0x02, 0x10,
909 0x02, 0x10, 0x02, 0x10, 0xfe, 0x1f};
910} -maskdata $filemask
911
912image create bitmap file_mod -background white -foreground blue -data {
913#define mod_width 14
914#define mod_height 15
915static unsigned char mod_bits[] = {
916 0xfe, 0x01, 0x02, 0x03, 0x7a, 0x05, 0x02, 0x09, 0x7a, 0x1f, 0x02, 0x10,
917 0xfa, 0x17, 0x02, 0x10, 0xfa, 0x17, 0x02, 0x10, 0xfa, 0x17, 0x02, 0x10,
918 0xfa, 0x17, 0x02, 0x10, 0xfe, 0x1f};
919} -maskdata $filemask
920
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500921image create bitmap file_fulltick -background white -foreground "#007000" -data {
922#define file_fulltick_width 14
923#define file_fulltick_height 15
924static unsigned char file_fulltick_bits[] = {
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500925 0xfe, 0x01, 0x02, 0x1a, 0x02, 0x0c, 0x02, 0x0c, 0x02, 0x16, 0x02, 0x16,
926 0x02, 0x13, 0x00, 0x13, 0x86, 0x11, 0x8c, 0x11, 0xd8, 0x10, 0xf2, 0x10,
927 0x62, 0x10, 0x02, 0x10, 0xfe, 0x1f};
928} -maskdata $filemask
929
930image create bitmap file_parttick -background white -foreground "#005050" -data {
931#define parttick_width 14
932#define parttick_height 15
933static unsigned char parttick_bits[] = {
934 0xfe, 0x01, 0x02, 0x03, 0x7a, 0x05, 0x02, 0x09, 0x7a, 0x1f, 0x02, 0x10,
935 0x7a, 0x14, 0x02, 0x16, 0x02, 0x13, 0x8a, 0x11, 0xda, 0x10, 0x72, 0x10,
936 0x22, 0x10, 0x02, 0x10, 0xfe, 0x1f};
937} -maskdata $filemask
938
939image create bitmap file_question -background white -foreground black -data {
940#define file_question_width 14
941#define file_question_height 15
942static unsigned char file_question_bits[] = {
943 0xfe, 0x01, 0x02, 0x02, 0xe2, 0x04, 0xf2, 0x09, 0x1a, 0x1b, 0x0a, 0x13,
944 0x82, 0x11, 0xc2, 0x10, 0x62, 0x10, 0x62, 0x10, 0x02, 0x10, 0x62, 0x10,
945 0x62, 0x10, 0x02, 0x10, 0xfe, 0x1f};
946} -maskdata $filemask
947
948image create bitmap file_removed -background white -foreground red -data {
949#define file_removed_width 14
950#define file_removed_height 15
951static unsigned char file_removed_bits[] = {
952 0xfe, 0x01, 0x02, 0x03, 0x02, 0x05, 0x02, 0x09, 0x02, 0x1f, 0x02, 0x10,
953 0x1a, 0x16, 0x32, 0x13, 0xe2, 0x11, 0xc2, 0x10, 0xe2, 0x11, 0x32, 0x13,
954 0x1a, 0x16, 0x02, 0x10, 0xfe, 0x1f};
955} -maskdata $filemask
956
957image create bitmap file_merge -background white -foreground blue -data {
958#define file_merge_width 14
959#define file_merge_height 15
960static unsigned char file_merge_bits[] = {
961 0xfe, 0x01, 0x02, 0x03, 0x62, 0x05, 0x62, 0x09, 0x62, 0x1f, 0x62, 0x10,
962 0xfa, 0x11, 0xf2, 0x10, 0x62, 0x10, 0x02, 0x10, 0xfa, 0x17, 0x02, 0x10,
963 0xfa, 0x17, 0x02, 0x10, 0xfe, 0x1f};
964} -maskdata $filemask
965
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500966set max_status_desc 0
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500967foreach i {
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500968 {__ i plain "Unmodified"}
969 {_M i mod "Modified"}
970 {M_ i fulltick "Checked in"}
971 {MM i parttick "Partially checked in"}
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500972
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500973 {_O o plain "Untracked"}
974 {A_ o fulltick "Added"}
975 {AM o parttick "Partially added"}
Shawn O. Pearcebd1e2b42006-11-06 22:03:05 -0500976 {AD o question "Added (but now gone)"}
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500977
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500978 {_D i question "Missing"}
979 {D_ i removed "Removed"}
980 {DD i removed "Removed"}
981 {DO i removed "Removed (still exists)"}
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500982
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500983 {UM i merge "Merge conflicts"}
984 {U_ i merge "Merge conflicts"}
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500985 } {
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500986 if {$max_status_desc < [string length [lindex $i 3]]} {
987 set max_status_desc [string length [lindex $i 3]]
988 }
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500989 set all_cols([lindex $i 0]) [lindex $i 1]
Shawn O. Pearce131f5032006-11-06 16:07:32 -0500990 set all_icons([lindex $i 0]) file_[lindex $i 2]
991 set all_descs([lindex $i 0]) [lindex $i 3]
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -0500992}
993unset filemask i
994
995######################################################################
996##
997## util
998
999proc error_popup {msg} {
1000 set w .error
1001 toplevel $w
1002 wm transient $w .
1003 show_msg $w $w $msg
1004}
1005
1006proc show_msg {w top msg} {
Shawn O. Pearceb8ce6f02006-11-07 00:20:56 -05001007 global gitdir appname mainfont
Shawn O. Pearce6e27d822006-11-06 20:03:36 -05001008
1009 message $w.m -text $msg -justify left -aspect 400
Shawn O. Pearceec6b4242006-11-06 20:50:59 -05001010 pack $w.m -side top -fill x -padx 5 -pady 10
1011 button $w.ok -text OK \
1012 -width 15 \
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001013 -font $mainfont \
Shawn O. Pearceec6b4242006-11-06 20:50:59 -05001014 -command "destroy $top"
Shawn O. Pearce6e27d822006-11-06 20:03:36 -05001015 pack $w.ok -side bottom
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001016 bind $top <Visibility> "grab $top; focus $top"
1017 bind $top <Key-Return> "destroy $top"
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -05001018 wm title $w "$appname ([lindex [file split \
1019 [file normalize [file dirname $gitdir]]] \
1020 end]): error"
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001021 tkwait window $top
1022}
1023
Shawn O. Pearce6e27d822006-11-06 20:03:36 -05001024proc hook_failed_popup {hook msg} {
Shawn O. Pearceec6b4242006-11-06 20:50:59 -05001025 global gitdir mainfont difffont appname
Shawn O. Pearce6e27d822006-11-06 20:03:36 -05001026
1027 set w .hookfail
1028 toplevel $w
1029 wm transient $w .
1030
1031 frame $w.m
1032 label $w.m.l1 -text "$hook hook failed:" \
1033 -anchor w \
1034 -justify left \
1035 -font [concat $mainfont bold]
1036 text $w.m.t \
1037 -background white -borderwidth 1 \
1038 -relief sunken \
1039 -width 80 -height 10 \
1040 -font $difffont \
1041 -yscrollcommand [list $w.m.sby set]
1042 label $w.m.l2 \
1043 -text {You must correct the above errors before committing.} \
1044 -anchor w \
1045 -justify left \
1046 -font [concat $mainfont bold]
1047 scrollbar $w.m.sby -command [list $w.m.t yview]
1048 pack $w.m.l1 -side top -fill x
1049 pack $w.m.l2 -side bottom -fill x
1050 pack $w.m.sby -side right -fill y
1051 pack $w.m.t -side left -fill both -expand 1
1052 pack $w.m -side top -fill both -expand 1 -padx 5 -pady 10
1053
1054 $w.m.t insert 1.0 $msg
1055 $w.m.t conf -state disabled
1056
1057 button $w.ok -text OK \
1058 -width 15 \
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001059 -font $mainfont \
Shawn O. Pearce6e27d822006-11-06 20:03:36 -05001060 -command "destroy $w"
1061 pack $w.ok -side bottom
1062
1063 bind $w <Visibility> "grab $w; focus $w"
1064 bind $w <Key-Return> "destroy $w"
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -05001065 wm title $w "$appname ([lindex [file split \
1066 [file normalize [file dirname $gitdir]]] \
1067 end]): error"
Shawn O. Pearce6e27d822006-11-06 20:03:36 -05001068 tkwait window $w
1069}
1070
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001071set next_console_id 0
1072
1073proc new_console {short_title long_title} {
Shawn O. Pearce37af79d2006-11-07 04:19:49 -05001074 global next_console_id console_data
1075 set w .console[incr next_console_id]
1076 set console_data($w) [list $short_title $long_title]
1077 return [console_init $w]
1078}
1079
1080proc console_init {w} {
1081 global console_cr console_data
Shawn O. Pearceee3dc932006-11-07 02:18:18 -05001082 global gitdir appname mainfont difffont
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001083
Shawn O. Pearceee3dc932006-11-07 02:18:18 -05001084 set console_cr($w) 1.0
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001085 toplevel $w
1086 frame $w.m
Shawn O. Pearce37af79d2006-11-07 04:19:49 -05001087 label $w.m.l1 -text "[lindex $console_data($w) 1]:" \
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001088 -anchor w \
1089 -justify left \
1090 -font [concat $mainfont bold]
1091 text $w.m.t \
1092 -background white -borderwidth 1 \
1093 -relief sunken \
1094 -width 80 -height 10 \
1095 -font $difffont \
1096 -state disabled \
1097 -yscrollcommand [list $w.m.sby set]
Shawn O. Pearce07123f42006-11-07 02:57:46 -05001098 label $w.m.s -anchor w \
1099 -justify left \
1100 -font [concat $mainfont bold]
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001101 scrollbar $w.m.sby -command [list $w.m.t yview]
1102 pack $w.m.l1 -side top -fill x
Shawn O. Pearce07123f42006-11-07 02:57:46 -05001103 pack $w.m.s -side bottom -fill x
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001104 pack $w.m.sby -side right -fill y
1105 pack $w.m.t -side left -fill both -expand 1
1106 pack $w.m -side top -fill both -expand 1 -padx 5 -pady 10
1107
Shawn O. Pearceee3dc932006-11-07 02:18:18 -05001108 button $w.ok -text {Running...} \
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001109 -width 15 \
1110 -font $mainfont \
1111 -state disabled \
1112 -command "destroy $w"
1113 pack $w.ok -side bottom
1114
1115 bind $w <Visibility> "focus $w"
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -05001116 wm title $w "$appname ([lindex [file split \
1117 [file normalize [file dirname $gitdir]]] \
1118 end]): [lindex $console_data($w) 0]"
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001119 return $w
1120}
1121
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -05001122proc console_exec {w cmd {after {}}} {
Shawn O. Pearcecc4b1c02006-11-06 23:47:05 -05001123 global tcl_platform
1124
1125 # -- Windows tosses the enviroment when we exec our child.
1126 # But most users need that so we have to relogin. :-(
1127 #
1128 if {$tcl_platform(platform) == {windows}} {
1129 set cmd [list sh --login -c "cd \"[pwd]\" && [join $cmd { }]"]
1130 }
1131
1132 # -- Tcl won't let us redirect both stdout and stderr to
1133 # the same pipe. So pass it through cat...
1134 #
1135 set cmd [concat | $cmd |& cat]
1136
1137 set fd_f [open $cmd r]
Shawn O. Pearceee3dc932006-11-07 02:18:18 -05001138 fconfigure $fd_f -blocking 0 -translation binary
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -05001139 fileevent $fd_f readable [list console_read $w $fd_f $after]
Shawn O. Pearcecc4b1c02006-11-06 23:47:05 -05001140}
1141
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -05001142proc console_read {w fd after} {
Shawn O. Pearce37af79d2006-11-07 04:19:49 -05001143 global console_cr console_data
Shawn O. Pearceee3dc932006-11-07 02:18:18 -05001144
Shawn O. Pearceee3dc932006-11-07 02:18:18 -05001145 set buf [read $fd]
Shawn O. Pearce37af79d2006-11-07 04:19:49 -05001146 if {$buf != {}} {
1147 if {![winfo exists $w]} {console_init $w}
1148 $w.m.t conf -state normal
1149 set c 0
1150 set n [string length $buf]
1151 while {$c < $n} {
1152 set cr [string first "\r" $buf $c]
1153 set lf [string first "\n" $buf $c]
1154 if {$cr < 0} {set cr [expr $n + 1]}
1155 if {$lf < 0} {set lf [expr $n + 1]}
Shawn O. Pearceee3dc932006-11-07 02:18:18 -05001156
Shawn O. Pearce37af79d2006-11-07 04:19:49 -05001157 if {$lf < $cr} {
1158 $w.m.t insert end [string range $buf $c $lf]
1159 set console_cr($w) [$w.m.t index {end -1c}]
1160 set c $lf
1161 incr c
1162 } else {
1163 $w.m.t delete $console_cr($w) end
1164 $w.m.t insert end "\n"
1165 $w.m.t insert end [string range $buf $c $cr]
1166 set c $cr
1167 incr c
1168 }
Shawn O. Pearceee3dc932006-11-07 02:18:18 -05001169 }
Shawn O. Pearce37af79d2006-11-07 04:19:49 -05001170 $w.m.t conf -state disabled
1171 $w.m.t see end
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001172 }
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001173
Shawn O. Pearce07123f42006-11-07 02:57:46 -05001174 fconfigure $fd -blocking 1
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001175 if {[eof $fd]} {
Shawn O. Pearce07123f42006-11-07 02:57:46 -05001176 if {[catch {close $fd}]} {
Shawn O. Pearce37af79d2006-11-07 04:19:49 -05001177 if {![winfo exists $w]} {console_init $w}
Shawn O. Pearce07123f42006-11-07 02:57:46 -05001178 $w.m.s conf -background red -text {Error: Command Failed}
Shawn O. Pearce37af79d2006-11-07 04:19:49 -05001179 $w.ok conf -text Close
1180 $w.ok conf -state normal
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -05001181 set ok 0
Shawn O. Pearce37af79d2006-11-07 04:19:49 -05001182 } elseif {[winfo exists $w]} {
Shawn O. Pearce07123f42006-11-07 02:57:46 -05001183 $w.m.s conf -background green -text {Success}
Shawn O. Pearce37af79d2006-11-07 04:19:49 -05001184 $w.ok conf -text Close
1185 $w.ok conf -state normal
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -05001186 set ok 1
Shawn O. Pearce07123f42006-11-07 02:57:46 -05001187 }
Shawn O. Pearceee3dc932006-11-07 02:18:18 -05001188 array unset console_cr $w
Shawn O. Pearce37af79d2006-11-07 04:19:49 -05001189 array unset console_data $w
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -05001190 if {$after != {}} {
1191 uplevel #0 $after $ok
1192 }
Shawn O. Pearce07123f42006-11-07 02:57:46 -05001193 return
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001194 }
Shawn O. Pearce07123f42006-11-07 02:57:46 -05001195 fconfigure $fd -blocking 0
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001196}
1197
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001198######################################################################
1199##
1200## ui commands
1201
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001202set starting_gitk_msg {Please wait... Starting gitk...}
Shawn O. Pearcecc4b1c02006-11-06 23:47:05 -05001203
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001204proc do_gitk {} {
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001205 global tcl_platform ui_status_value starting_gitk_msg
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001206
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001207 set ui_status_value $starting_gitk_msg
Shawn O. Pearcee57ca852006-11-06 21:34:10 -05001208 after 10000 {
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001209 if {$ui_status_value == $starting_gitk_msg} {
1210 set ui_status_value {Ready.}
1211 }
1212 }
1213
Shawn O. Pearcecc4b1c02006-11-06 23:47:05 -05001214 if {$tcl_platform(platform) == {windows}} {
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001215 exec sh -c gitk &
1216 } else {
1217 exec gitk &
1218 }
1219}
1220
1221proc do_quit {} {
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001222 global gitdir ui_comm
1223
1224 set save [file join $gitdir GITGUI_MSG]
Shawn O. Pearceec6b4242006-11-06 20:50:59 -05001225 set msg [string trim [$ui_comm get 0.0 end]]
1226 if {[$ui_comm edit modified] && $msg != {}} {
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001227 catch {
1228 set fd [open $save w]
1229 puts $fd [string trim [$ui_comm get 0.0 end]]
1230 close $fd
1231 }
Shawn O. Pearceec6b4242006-11-06 20:50:59 -05001232 } elseif {$msg == {} && [file exists $save]} {
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001233 file delete $save
1234 }
1235
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001236 destroy .
1237}
1238
1239proc do_rescan {} {
1240 update_status
1241}
1242
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001243proc do_checkin_all {} {
1244 global checkin_active ui_status_value
1245
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001246 if {$checkin_active || ![lock_index begin-update]} return
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001247
1248 set checkin_active 1
1249 set ui_status_value {Checking in all files...}
1250 after 1 {
1251 with_update_index {
1252 foreach path [array names file_states] {
1253 set s $file_states($path)
1254 set m [lindex $s 0]
1255 switch -- $m {
1256 AM -
1257 MM -
1258 _M -
1259 _D {toggle_mode $path}
1260 }
1261 }
1262 }
1263 set checkin_active 0
1264 set ui_status_value {Ready.}
1265 }
1266}
1267
1268proc do_signoff {} {
1269 global ui_comm
1270
1271 catch {
1272 set me [exec git var GIT_COMMITTER_IDENT]
1273 if {[regexp {(.*) [0-9]+ [-+0-9]+$} $me me name]} {
1274 set str "Signed-off-by: $name"
1275 if {[$ui_comm get {end -1c linestart} {end -1c}] != $str} {
1276 $ui_comm insert end "\n"
1277 $ui_comm insert end $str
1278 $ui_comm see end
1279 }
1280 }
1281 }
1282}
1283
Shawn O. Pearcee57ca852006-11-06 21:34:10 -05001284proc do_amend_last {} {
1285 load_last_commit
1286}
1287
Shawn O. Pearce6e27d822006-11-06 20:03:36 -05001288proc do_commit {} {
Shawn O. Pearceec6b4242006-11-06 20:50:59 -05001289 commit_tree
Shawn O. Pearce6e27d822006-11-06 20:03:36 -05001290}
1291
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001292# shift == 1: left click
1293# 3: right click
1294proc click {w x y shift wx wy} {
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001295 global ui_index ui_other
1296
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001297 set pos [split [$w index @$x,$y] .]
1298 set lno [lindex $pos 0]
1299 set col [lindex $pos 1]
1300 set path [$w get $lno.1 $lno.end]
1301 if {$path == {}} return
1302
1303 if {$col > 0 && $shift == 1} {
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001304 $ui_index tag remove in_diff 0.0 end
1305 $ui_other tag remove in_diff 0.0 end
1306 $w tag add in_diff $lno.0 [expr $lno + 1].0
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001307 show_diff $path
1308 }
1309}
1310
1311proc unclick {w x y} {
1312 set pos [split [$w index @$x,$y] .]
1313 set lno [lindex $pos 0]
1314 set col [lindex $pos 1]
1315 set path [$w get $lno.1 $lno.end]
1316 if {$path == {}} return
1317
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001318 if {$col == 0} {
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001319 toggle_mode $path
1320 }
1321}
1322
1323######################################################################
1324##
1325## ui init
1326
1327set mainfont {Helvetica 10}
1328set difffont {Courier 10}
1329set maincursor [. cget -cursor]
1330
Shawn O. Pearce66144892006-11-07 00:53:39 -05001331switch -glob -- "$tcl_platform(platform),$tcl_platform(os)" {
1332windows,* {set M1B Control; set M1T Ctrl}
1333unix,Darwin {set M1B M1; set M1T Cmd}
1334default {set M1B M1; set M1T M1}
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001335}
1336
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001337# -- Menu Bar
1338menu .mbar -tearoff 0
1339.mbar add cascade -label Project -menu .mbar.project
1340.mbar add cascade -label Commit -menu .mbar.commit
1341.mbar add cascade -label Fetch -menu .mbar.fetch
1342.mbar add cascade -label Pull -menu .mbar.pull
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001343.mbar add cascade -label Push -menu .mbar.push
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001344. configure -menu .mbar
1345
1346# -- Project Menu
1347menu .mbar.project
Shawn O. Pearce6f6eed22006-11-06 18:22:19 -05001348.mbar.project add command -label Visualize \
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001349 -command do_gitk \
1350 -font $mainfont
1351.mbar.project add command -label Quit \
1352 -command do_quit \
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001353 -accelerator $M1T-Q \
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001354 -font $mainfont
1355
1356# -- Commit Menu
1357menu .mbar.commit
1358.mbar.commit add command -label Rescan \
1359 -command do_rescan \
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001360 -accelerator F5 \
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001361 -font $mainfont
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001362lappend disable_on_lock \
1363 [list .mbar.commit entryconf [.mbar.commit index last] -state]
Shawn O. Pearcee57ca852006-11-06 21:34:10 -05001364.mbar.commit add command -label {Amend Last Commit} \
1365 -command do_amend_last \
1366 -font $mainfont
1367lappend disable_on_lock \
1368 [list .mbar.commit entryconf [.mbar.commit index last] -state]
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001369.mbar.commit add command -label {Check-in All Files} \
1370 -command do_checkin_all \
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001371 -accelerator $M1T-U \
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001372 -font $mainfont
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001373lappend disable_on_lock \
1374 [list .mbar.commit entryconf [.mbar.commit index last] -state]
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001375.mbar.commit add command -label {Sign Off} \
1376 -command do_signoff \
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001377 -accelerator $M1T-S \
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001378 -font $mainfont
1379.mbar.commit add command -label Commit \
1380 -command do_commit \
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001381 -accelerator $M1T-Return \
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001382 -font $mainfont
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001383lappend disable_on_lock \
1384 [list .mbar.commit entryconf [.mbar.commit index last] -state]
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001385
1386# -- Fetch Menu
1387menu .mbar.fetch
1388
1389# -- Pull Menu
1390menu .mbar.pull
1391
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001392# -- Push Menu
1393menu .mbar.push
1394
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001395# -- Main Window Layout
1396panedwindow .vpane -orient vertical
1397panedwindow .vpane.files -orient horizontal
Shawn O. Pearce6f6eed22006-11-06 18:22:19 -05001398.vpane add .vpane.files -sticky nsew -height 100 -width 400
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001399pack .vpane -anchor n -side top -fill both -expand 1
1400
1401# -- Index File List
1402set ui_index .vpane.files.index.list
1403frame .vpane.files.index -height 100 -width 400
1404label .vpane.files.index.title -text {Modified Files} \
1405 -background green \
1406 -font $mainfont
1407text $ui_index -background white -borderwidth 0 \
1408 -width 40 -height 10 \
1409 -font $mainfont \
1410 -yscrollcommand {.vpane.files.index.sb set} \
1411 -cursor $maincursor \
1412 -state disabled
1413scrollbar .vpane.files.index.sb -command [list $ui_index yview]
1414pack .vpane.files.index.title -side top -fill x
1415pack .vpane.files.index.sb -side right -fill y
1416pack $ui_index -side left -fill both -expand 1
1417.vpane.files add .vpane.files.index -sticky nsew
1418
1419# -- Other (Add) File List
1420set ui_other .vpane.files.other.list
1421frame .vpane.files.other -height 100 -width 100
1422label .vpane.files.other.title -text {Untracked Files} \
1423 -background red \
1424 -font $mainfont
1425text $ui_other -background white -borderwidth 0 \
1426 -width 40 -height 10 \
1427 -font $mainfont \
1428 -yscrollcommand {.vpane.files.other.sb set} \
1429 -cursor $maincursor \
1430 -state disabled
1431scrollbar .vpane.files.other.sb -command [list $ui_other yview]
1432pack .vpane.files.other.title -side top -fill x
1433pack .vpane.files.other.sb -side right -fill y
1434pack $ui_other -side left -fill both -expand 1
1435.vpane.files add .vpane.files.other -sticky nsew
1436
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001437$ui_index tag conf in_diff -font [concat $mainfont bold]
1438$ui_other tag conf in_diff -font [concat $mainfont bold]
1439
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001440# -- Diff Header
1441set ui_fname_value {}
1442set ui_fstatus_value {}
Shawn O. Pearce6f6eed22006-11-06 18:22:19 -05001443frame .vpane.diff -height 200 -width 400
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001444frame .vpane.diff.header
1445label .vpane.diff.header.l1 -text {File:} -font $mainfont
1446label .vpane.diff.header.l2 -textvariable ui_fname_value \
1447 -anchor w \
1448 -justify left \
1449 -font $mainfont
1450label .vpane.diff.header.l3 -text {Status:} -font $mainfont
1451label .vpane.diff.header.l4 -textvariable ui_fstatus_value \
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001452 -width $max_status_desc \
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001453 -anchor w \
1454 -justify left \
1455 -font $mainfont
1456pack .vpane.diff.header.l1 -side left
1457pack .vpane.diff.header.l2 -side left -fill x
1458pack .vpane.diff.header.l4 -side right
1459pack .vpane.diff.header.l3 -side right
1460
1461# -- Diff Body
1462frame .vpane.diff.body
1463set ui_diff .vpane.diff.body.t
1464text $ui_diff -background white -borderwidth 0 \
Shawn O. Pearce6f6eed22006-11-06 18:22:19 -05001465 -width 80 -height 15 -wrap none \
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001466 -font $difffont \
1467 -xscrollcommand {.vpane.diff.body.sbx set} \
1468 -yscrollcommand {.vpane.diff.body.sby set} \
1469 -cursor $maincursor \
1470 -state disabled
1471scrollbar .vpane.diff.body.sbx -orient horizontal \
1472 -command [list $ui_diff xview]
1473scrollbar .vpane.diff.body.sby -orient vertical \
1474 -command [list $ui_diff yview]
1475pack .vpane.diff.body.sbx -side bottom -fill x
1476pack .vpane.diff.body.sby -side right -fill y
1477pack $ui_diff -side left -fill both -expand 1
1478pack .vpane.diff.header -side top -fill x
1479pack .vpane.diff.body -side bottom -fill both -expand 1
1480.vpane add .vpane.diff -stick nsew
1481
1482$ui_diff tag conf dm -foreground red
1483$ui_diff tag conf dp -foreground blue
1484$ui_diff tag conf da -font [concat $difffont bold]
1485$ui_diff tag conf di -foreground "#00a000"
1486$ui_diff tag conf dni -foreground "#a000a0"
1487$ui_diff tag conf bold -font [concat $difffont bold]
1488
1489# -- Commit Area
Shawn O. Pearcee57ca852006-11-06 21:34:10 -05001490frame .vpane.commarea -height 170
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001491.vpane add .vpane.commarea -stick nsew
1492
1493# -- Commit Area Buttons
1494frame .vpane.commarea.buttons
1495label .vpane.commarea.buttons.l -text {} \
1496 -anchor w \
1497 -justify left \
1498 -font $mainfont
1499pack .vpane.commarea.buttons.l -side top -fill x
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001500pack .vpane.commarea.buttons -side left -fill y
1501
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001502button .vpane.commarea.buttons.rescan -text {Rescan} \
1503 -command do_rescan \
1504 -font $mainfont
1505pack .vpane.commarea.buttons.rescan -side top -fill x
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001506lappend disable_on_lock {.vpane.commarea.buttons.rescan conf -state}
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001507
Shawn O. Pearcee57ca852006-11-06 21:34:10 -05001508button .vpane.commarea.buttons.amend -text {Amend Last} \
1509 -command do_amend_last \
1510 -font $mainfont
1511pack .vpane.commarea.buttons.amend -side top -fill x
1512lappend disable_on_lock {.vpane.commarea.buttons.amend conf -state}
1513
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001514button .vpane.commarea.buttons.ciall -text {Check-in All} \
1515 -command do_checkin_all \
1516 -font $mainfont
1517pack .vpane.commarea.buttons.ciall -side top -fill x
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001518lappend disable_on_lock {.vpane.commarea.buttons.ciall conf -state}
Shawn O. Pearce131f5032006-11-06 16:07:32 -05001519
1520button .vpane.commarea.buttons.signoff -text {Sign Off} \
1521 -command do_signoff \
1522 -font $mainfont
1523pack .vpane.commarea.buttons.signoff -side top -fill x
1524
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001525button .vpane.commarea.buttons.commit -text {Commit} \
1526 -command do_commit \
1527 -font $mainfont
1528pack .vpane.commarea.buttons.commit -side top -fill x
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001529lappend disable_on_lock {.vpane.commarea.buttons.commit conf -state}
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001530
1531# -- Commit Message Buffer
1532frame .vpane.commarea.buffer
1533set ui_comm .vpane.commarea.buffer.t
Shawn O. Pearcebd1e2b42006-11-06 22:03:05 -05001534set ui_coml .vpane.commarea.buffer.l
1535label $ui_coml -text {Commit Message:} \
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001536 -anchor w \
1537 -justify left \
1538 -font $mainfont
Shawn O. Pearcebd1e2b42006-11-06 22:03:05 -05001539trace add variable commit_type write {uplevel #0 {
1540 switch -glob $commit_type \
1541 initial {$ui_coml conf -text {Initial Commit Message:}} \
1542 amend {$ui_coml conf -text {Amended Commit Message:}} \
1543 merge {$ui_coml conf -text {Merge Commit Message:}} \
1544 * {$ui_coml conf -text {Commit Message:}}
1545}}
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001546text $ui_comm -background white -borderwidth 1 \
1547 -relief sunken \
1548 -width 75 -height 10 -wrap none \
1549 -font $difffont \
1550 -yscrollcommand {.vpane.commarea.buffer.sby set} \
1551 -cursor $maincursor
1552scrollbar .vpane.commarea.buffer.sby -command [list $ui_comm yview]
Shawn O. Pearcebd1e2b42006-11-06 22:03:05 -05001553pack $ui_coml -side top -fill x
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001554pack .vpane.commarea.buffer.sby -side right -fill y
1555pack $ui_comm -side left -fill y
1556pack .vpane.commarea.buffer -side left -fill y
1557
1558# -- Status Bar
1559set ui_status_value {Initializing...}
1560label .status -textvariable ui_status_value \
1561 -anchor w \
1562 -justify left \
1563 -borderwidth 1 \
1564 -relief sunken \
1565 -font $mainfont
1566pack .status -anchor w -side bottom -fill x
1567
1568# -- Key Bindings
Shawn O. Pearceec6b4242006-11-06 20:50:59 -05001569bind $ui_comm <$M1B-Key-Return> {do_commit;break}
Shawn O. Pearce07123f42006-11-07 02:57:46 -05001570bind . <Destroy> do_quit
1571bind all <Key-F5> do_rescan
1572bind all <$M1B-Key-r> do_rescan
1573bind all <$M1B-Key-R> do_rescan
1574bind . <$M1B-Key-s> do_signoff
1575bind . <$M1B-Key-S> do_signoff
1576bind . <$M1B-Key-u> do_checkin_all
1577bind . <$M1B-Key-U> do_checkin_all
1578bind . <$M1B-Key-Return> do_commit
1579bind all <$M1B-Key-q> do_quit
1580bind all <$M1B-Key-Q> do_quit
1581bind all <$M1B-Key-w> {destroy [winfo toplevel %W]}
1582bind all <$M1B-Key-W> {destroy [winfo toplevel %W]}
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001583foreach i [list $ui_index $ui_other] {
1584 bind $i <Button-1> {click %W %x %y 1 %X %Y; break}
1585 bind $i <Button-3> {click %W %x %y 3 %X %Y; break}
1586 bind $i <ButtonRelease-1> {unclick %W %x %y; break}
1587}
Shawn O. Pearcee210e672006-11-06 19:12:58 -05001588unset i M1B M1T
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001589
1590######################################################################
1591##
1592## main
1593
Shawn O. Pearceb8ce6f02006-11-07 00:20:56 -05001594set appname [lindex [file split $argv0] end]
1595set gitdir {}
1596
1597if {[catch {set cdup [exec git rev-parse --show-cdup]} err]} {
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001598 show_msg {} . "Cannot find the git directory: $err"
1599 exit 1
1600}
Shawn O. Pearcebd1e2b42006-11-06 22:03:05 -05001601if {$cdup != ""} {
1602 cd $cdup
1603}
1604unset cdup
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001605
Shawn O. Pearceb8ce6f02006-11-07 00:20:56 -05001606if {[catch {set gitdir [exec git rev-parse --git-dir]} err]} {
1607 show_msg {} . "Cannot find the git directory: $err"
1608 exit 1
1609}
1610
Shawn O. Pearceec6b4242006-11-06 20:50:59 -05001611if {$appname == {git-citool}} {
1612 set single_commit 1
1613}
1614
1615wm title . "$appname ([file normalize [file dirname $gitdir]])"
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001616focus -force $ui_comm
Shawn O. Pearce0d4f3eb2006-11-07 04:26:02 -05001617load_repo_config
Shawn O. Pearce8c0ce432006-11-06 23:13:23 -05001618load_all_remotes
1619populate_remote_menu .mbar.fetch From fetch_from
1620populate_remote_menu .mbar.push To push_to
Shawn O. Pearced33ba5f2006-11-07 05:02:15 -05001621populate_pull_menu .mbar.pull
Shawn O. Pearcecb07fc22006-11-06 14:20:27 -05001622update_status