2 # Tcl ignores the next line -*- tcl -*- \
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.
10 ######################################################################
14 proc load_repo_config
{} {
16 global cfg_trust_mtime
18 array
unset repo_config
20 set fd_rc
[open
"| git repo-config --list" r
]
21 while {[gets
$fd_rc line
] >= 0} {
22 if {[regexp
{^
([^
=]+)=(.
*)$
} $line line name value
]} {
23 lappend repo_config
($name) $value
29 if {[catch
{set cfg_trust_mtime \
30 [lindex
$repo_config(gui.trustmtime
) 0]
32 set cfg_trust_mtime false
36 proc save_my_config
{} {
38 global cfg_trust_mtime
40 if {[catch
{set rc_trustMTime
$repo_config(gui.trustmtime
)}]} {
41 set rc_trustMTime
[list false
]
43 if {$cfg_trust_mtime != [lindex
$rc_trustMTime 0]} {
44 exec git repo-config gui.trustMTime
$cfg_trust_mtime
45 set repo_config
(gui.trustmtime
) [list
$cfg_trust_mtime]
48 set cfg_geometry
[list \
50 [.vpane sash coord
0] \
51 [.vpane.files sash coord
0] \
53 if {[catch
{set rc_geometry
$repo_config(gui.geometry
)}]} {
54 set rc_geometry
[list
[list
]]
56 if {$cfg_geometry != [lindex
$rc_geometry 0]} {
57 exec git repo-config gui.geometry
$cfg_geometry
58 set repo_config
(gui.geometry
) [list
$cfg_geometry]
62 ######################################################################
66 set appname
[lindex
[file split $argv0] end
]
68 set GIT_COMMITTER_IDENT
{}
70 if {[catch
{set cdup
[exec git rev-parse
--show-cdup]} err
]} {
71 show_msg
{} .
"Cannot find the git directory: $err"
79 if {[catch
{set gitdir
[exec git rev-parse
--git-dir]} err
]} {
80 show_msg
{} .
"Cannot find the git directory: $err"
84 if {$appname == {git-citool
}} {
90 ######################################################################
99 set update_index_fd
{}
101 set disable_on_lock
[list
]
102 set index_lock_type none
108 proc lock_index
{type} {
109 global index_lock_type disable_on_lock
111 if {$index_lock_type == {none
}} {
112 set index_lock_type
$type
113 foreach w
$disable_on_lock {
114 uplevel
#0 $w disabled
117 } elseif
{$index_lock_type == {begin-update
} && $type == {update
}} {
118 set index_lock_type
$type
124 proc unlock_index
{} {
125 global index_lock_type disable_on_lock
127 set index_lock_type none
128 foreach w
$disable_on_lock {
133 ######################################################################
137 proc repository_state
{hdvar ctvar
} {
139 upvar
$hdvar hd
$ctvar ct
141 if {[catch
{set hd
[exec git rev-parse
--verify HEAD
]}]} {
143 } elseif
{[file exists
[file join $gitdir MERGE_HEAD
]]} {
150 proc update_status
{{final Ready.
}} {
151 global HEAD PARENT commit_type
152 global ui_index ui_other ui_status_value ui_comm
153 global status_active file_states
154 global cfg_trust_mtime
156 if {$status_active ||
![lock_index
read]} return
158 repository_state new_HEAD new_type
159 if {$commit_type == {amend
}
160 && $new_type == {normal
}
161 && $new_HEAD == $HEAD} {
165 set commit_type
$new_type
168 array
unset file_states
170 if {![$ui_comm edit modified
]
171 ||
[string trim
[$ui_comm get
0.0 end
]] == {}} {
172 if {[load_message GITGUI_MSG
]} {
173 } elseif
{[load_message MERGE_MSG
]} {
174 } elseif
{[load_message SQUASH_MSG
]} {
176 $ui_comm edit modified false
180 if {$cfg_trust_mtime == {true
}} {
181 update_status_stage2
{} $final
184 set ui_status_value
{Refreshing
file status...
}
185 set fd_rf
[open
"| git update-index -q --unmerged --refresh" r
]
186 fconfigure
$fd_rf -blocking 0 -translation binary
187 fileevent
$fd_rf readable
[list update_status_stage2
$fd_rf $final]
191 proc update_status_stage2
{fd final
} {
192 global gitdir PARENT commit_type
193 global ui_index ui_other ui_status_value ui_comm
195 global buf_rdi buf_rdf buf_rlo
199 if {![eof
$fd]} return
203 set ls_others
[list | git ls-files
--others -z \
204 --exclude-per-directory=.gitignore
]
205 set info_exclude
[file join $gitdir info exclude
]
206 if {[file readable
$info_exclude]} {
207 lappend ls_others
"--exclude-from=$info_exclude"
215 set ui_status_value
{Scanning
for modified files ...
}
216 set fd_di
[open
"| git diff-index --cached -z $PARENT" r
]
217 set fd_df
[open
"| git diff-files -z" r
]
218 set fd_lo
[open
$ls_others r
]
220 fconfigure
$fd_di -blocking 0 -translation binary
221 fconfigure
$fd_df -blocking 0 -translation binary
222 fconfigure
$fd_lo -blocking 0 -translation binary
223 fileevent
$fd_di readable
[list read_diff_index
$fd_di $final]
224 fileevent
$fd_df readable
[list read_diff_files
$fd_df $final]
225 fileevent
$fd_lo readable
[list read_ls_others
$fd_lo $final]
228 proc load_message
{file} {
229 global gitdir ui_comm
231 set f
[file join $gitdir $file]
232 if {[file isfile
$f]} {
233 if {[catch
{set fd
[open
$f r
]}]} {
236 set content
[string trim
[read $fd]]
238 $ui_comm delete
0.0 end
239 $ui_comm insert end
$content
245 proc read_diff_index
{fd final
} {
248 append buf_rdi
[read $fd]
250 set n
[string length
$buf_rdi]
252 set z1
[string first
"\0" $buf_rdi $c]
255 set z2
[string first
"\0" $buf_rdi $z1]
261 [string range
$buf_rdi $z1 $z2] \
262 [string index
$buf_rdi [expr $z1 - 2]]_
266 set buf_rdi
[string range
$buf_rdi $c end
]
271 status_eof
$fd buf_rdi
$final
274 proc read_diff_files
{fd final
} {
277 append buf_rdf
[read $fd]
279 set n
[string length
$buf_rdf]
281 set z1
[string first
"\0" $buf_rdf $c]
284 set z2
[string first
"\0" $buf_rdf $z1]
290 [string range
$buf_rdf $z1 $z2] \
291 _
[string index
$buf_rdf [expr $z1 - 2]]
295 set buf_rdf
[string range
$buf_rdf $c end
]
300 status_eof
$fd buf_rdf
$final
303 proc read_ls_others
{fd final
} {
306 append buf_rlo
[read $fd]
307 set pck
[split $buf_rlo "\0"]
308 set buf_rlo
[lindex
$pck end
]
309 foreach p
[lrange
$pck 0 end-1
] {
312 status_eof
$fd buf_rlo
$final
315 proc status_eof
{fd buf final
} {
316 global status_active ui_status_value
323 if {[incr status_active
-1] == 0} {
327 set ui_status_value
$final
332 ######################################################################
337 global ui_diff ui_fname_value ui_fstatus_value ui_index ui_other
339 $ui_diff conf
-state normal
340 $ui_diff delete
0.0 end
341 $ui_diff conf
-state disabled
343 set ui_fname_value
{}
344 set ui_fstatus_value
{}
346 $ui_index tag remove in_diff
0.0 end
347 $ui_other tag remove in_diff
0.0 end
350 proc reshow_diff
{} {
351 global ui_fname_value ui_status_value file_states
353 if {$ui_fname_value != {} && [array names file_states \
354 -exact $ui_fname_value] != {}} {
355 show_diff
$ui_fname_value
361 proc show_diff
{path
{w
{}} {lno
{}}} {
362 global file_states file_lists
363 global PARENT diff_3way diff_active
364 global ui_diff ui_fname_value ui_fstatus_value ui_status_value
366 if {$diff_active ||
![lock_index
read]} return
369 if {$w == {} ||
$lno == {}} {
370 foreach w
[array names file_lists
] {
371 set lno
[lsearch
-sorted $file_lists($w) $path]
378 if {$w != {} && $lno >= 1} {
379 $w tag add in_diff
$lno.0 [expr $lno + 1].0
382 set s
$file_states($path)
386 set ui_fname_value
[escape_path
$path]
387 set ui_fstatus_value
[mapdesc
$m $path]
388 set ui_status_value
"Loading diff of [escape_path $path]..."
390 set cmd
[list | git diff-index
-p $PARENT -- $path]
395 set cmd
[list | git diff-index
-p -c $PARENT $path]
399 set fd
[open
$path r
]
400 set content
[read $fd]
405 set ui_status_value
"Unable to display [escape_path $path]"
406 error_popup
"Error loading file:\n$err"
409 $ui_diff conf
-state normal
410 $ui_diff insert end
$content
411 $ui_diff conf
-state disabled
414 set ui_status_value
{Ready.
}
419 if {[catch
{set fd
[open
$cmd r
]} err
]} {
422 set ui_status_value
"Unable to display [escape_path $path]"
423 error_popup
"Error loading diff:\n$err"
427 fconfigure
$fd -blocking 0 -translation auto
428 fileevent
$fd readable
[list read_diff
$fd]
431 proc read_diff
{fd
} {
432 global ui_diff ui_status_value diff_3way diff_active
434 while {[gets
$fd line
] >= 0} {
435 if {[string match
{diff --git *} $line]} continue
436 if {[string match
{diff --combined *} $line]} continue
437 if {[string match
{--- *} $line]} continue
438 if {[string match
{+++ *} $line]} continue
439 if {[string match index
* $line]} {
440 if {[string first
, $line] >= 0} {
445 $ui_diff conf
-state normal
447 set x
[string index
$line 0]
452 default
{set tags
{}}
455 set x
[string range
$line 0 1]
457 default
{set tags
{}}
459 "++" {set tags dp
; set x
" +"}
460 " +" {set tags
{di bold
}; set x
"++"}
461 "+ " {set tags dni
; set x
"-+"}
462 "--" {set tags dm
; set x
" -"}
463 " -" {set tags
{dm bold
}; set x
"--"}
464 "- " {set tags di
; set x
"+-"}
465 default
{set tags
{}}
467 set line
[string replace
$line 0 1 $x]
469 $ui_diff insert end
$line $tags
470 $ui_diff insert end
"\n"
471 $ui_diff conf
-state disabled
478 set ui_status_value
{Ready.
}
482 ######################################################################
486 proc load_last_commit
{} {
487 global HEAD PARENT commit_type ui_comm
489 if {$commit_type == {amend
}} return
490 if {$commit_type != {normal
}} {
491 error_popup
"Can't amend a $commit_type commit."
499 set fd
[open
"| git cat-file commit $HEAD" r
]
500 while {[gets
$fd line
] > 0} {
501 if {[string match
{parent
*} $line]} {
502 set parent
[string range
$line 7 end
]
506 set msg
[string trim
[read $fd]]
509 error_popup
"Error loading commit data for amend:\n$err"
513 if {$parent_count == 0} {
514 set commit_type amend
518 } elseif
{$parent_count == 1} {
519 set commit_type amend
521 $ui_comm delete
0.0 end
522 $ui_comm insert end
$msg
523 $ui_comm edit modified false
527 error_popup
{You can
't amend a merge commit.}
532 proc commit_tree {} {
533 global tcl_platform HEAD gitdir commit_type file_states
534 global commit_active ui_status_value
537 if {$commit_active || ![lock_index update]} return
539 # -- Our in memory state should match the repository.
541 repository_state curHEAD cur_type
542 if {$commit_type == {amend}
543 && $cur_type == {normal}
544 && $curHEAD == $HEAD} {
545 } elseif {$commit_type != $cur_type || $HEAD != $curHEAD} {
546 error_popup {Last scanned state does not match repository state.
548 Its highly likely that another Git program modified the
549 repository since our last scan. A rescan is required
557 # -- At least one file should differ in the index.
560 foreach path [array names file_states] {
561 set s $file_states($path)
562 switch -glob -- [lindex $s 0] {
566 M? {set files_ready 1; break}
568 error_popup "Unmerged files cannot be committed.
570 File [escape_path $path] has merge conflicts.
571 You must resolve them and include the file before committing.
577 error_popup "Unknown file state [lindex $s 0] detected.
579 File [escape_path $path] cannot be committed by this program.
585 error_popup {No included files to commit.
587 You must include at least 1 file before you can commit.
593 # -- A message is required.
595 set msg [string trim [$ui_comm get 1.0 end]]
597 error_popup {Please supply a commit message.
599 A good commit message has the following format:
601 - First line: Describe in one sentance what you did.
603 - Remaining lines: Describe why this change is good.
609 # -- Ask the pre-commit hook for the go-ahead.
611 set pchook [file join $gitdir hooks pre-commit]
612 if {$tcl_platform(platform) == {windows} && [file isfile $pchook]} {
613 set pchook [list sh -c \
614 "if test -x \"$pchook\"; then exec \"$pchook\"; fi"]
615 } elseif {[file executable $pchook]} {
616 set pchook [list $pchook]
620 if {$pchook != {} && [catch {eval exec $pchook} err]} {
621 hook_failed_popup pre-commit $err
626 # -- Write the tree in the background.
629 set ui_status_value {Committing changes...}
631 set fd_wt [open "| git write-tree" r]
632 fileevent $fd_wt readable [list commit_stage2 $fd_wt $curHEAD $msg]
635 proc commit_stage2 {fd_wt curHEAD msg} {
636 global single_commit gitdir HEAD PARENT commit_type
637 global commit_active ui_status_value ui_comm
643 if {$tree_id == {}} {
644 error_popup "write-tree failed"
646 set ui_status_value {Commit failed.}
651 # -- Create the commit.
653 set cmd [list git commit-tree $tree_id]
655 lappend cmd -p $PARENT
657 if {$commit_type == {merge}} {
659 set fd_mh [open [file join $gitdir MERGE_HEAD] r]
660 while {[gets $fd_mh merge_head] >= 0} {
661 lappend cmd -p $merge_head
665 error_popup "Loading MERGE_HEAD failed:\n$err"
667 set ui_status_value {Commit failed.}
673 # git commit-tree writes to stderr during initial commit.
674 lappend cmd 2>/dev/null
677 if {[catch {set cmt_id [eval exec $cmd]} err]} {
678 error_popup "commit-tree failed:\n$err"
680 set ui_status_value {Commit failed.}
685 # -- Update the HEAD ref.
688 if {$commit_type != {normal}} {
689 append reflogm " ($commit_type)"
691 set i [string first "\n" $msg]
693 append reflogm {: } [string range $msg 0 [expr $i - 1]]
695 append reflogm {: } $msg
697 set cmd [list git update-ref -m $reflogm HEAD $cmt_id $curHEAD]
698 if {[catch {eval exec $cmd} err]} {
699 error_popup "update-ref failed:\n$err"
701 set ui_status_value {Commit failed.}
706 # -- Cleanup after ourselves.
708 catch {file delete [file join $gitdir MERGE_HEAD]}
709 catch {file delete [file join $gitdir MERGE_MSG]}
710 catch {file delete [file join $gitdir SQUASH_MSG]}
711 catch {file delete [file join $gitdir GITGUI_MSG]}
713 # -- Let rerere do its thing.
715 if {[file isdirectory [file join $gitdir rr-cache]]} {
716 catch {exec git rerere}
719 $ui_comm delete 0.0 end
720 $ui_comm edit modified false
723 if {$single_commit} do_quit
725 # -- Update status without invoking any git commands.
728 set commit_type normal
732 foreach path [array names file_states] {
733 set s $file_states($path)
738 D? {set m _[string index $m 1]}
742 unset file_states($path)
744 lset file_states($path) 0 $m
751 set ui_status_value \
752 "Changes committed as [string range $cmt_id 0 7]."
755 ######################################################################
759 proc fetch_from {remote} {
760 set w [new_console "fetch $remote" \
761 "Fetching new changes from $remote"]
762 set cmd [list git fetch]
767 proc pull_remote {remote branch} {
768 global HEAD commit_type
771 if {![lock_index update]} return
773 # -- Our in memory state should match the repository.
775 repository_state curHEAD cur_type
776 if {$commit_type != $cur_type || $HEAD != $curHEAD} {
777 error_popup {Last scanned state does not match repository state.
779 Its highly likely that another Git program modified the
780 repository since our last scan. A rescan is required
781 before a pull can be started.
788 # -- No differences should exist before a pull.
790 if {[array size file_states] != 0} {
791 error_popup {Uncommitted but modified files are present.
793 You should not perform a pull with unmodified files in your working
794 directory as Git would be unable to recover from an incorrect merge.
796 Commit or throw away all changes before starting a pull operation.
802 set w [new_console "pull $remote $branch" \
803 "Pulling new changes from branch $branch in $remote"]
804 set cmd [list git pull]
807 console_exec $w $cmd [list post_pull_remote $remote $branch]
810 proc post_pull_remote {remote branch success} {
811 global HEAD PARENT commit_type
812 global ui_status_value
816 repository_state HEAD commit_type
818 set $ui_status_value {Ready.}
820 update_status "Conflicts detected while pulling $branch from $remote."
824 proc push_to {remote} {
825 set w [new_console "push $remote" \
826 "Pushing changes to $remote"]
827 set cmd [list git push]
832 ######################################################################
836 proc mapcol {state path} {
837 global all_cols ui_other
839 if {[catch {set r $all_cols($state)}]} {
840 puts "error: no column for state={$state} $path"
846 proc mapicon {state path} {
849 if {[catch {set r $all_icons($state)}]} {
850 puts "error: no icon for state={$state} $path"
856 proc mapdesc {state path} {
859 if {[catch {set r $all_descs($state)}]} {
860 puts "error: no desc for state={$state} $path"
866 proc escape_path {path} {
867 regsub -all "\n" $path "\\n" path
873 proc merge_state {path new_state} {
874 global file_states next_icon_id
876 set s0 [string index $new_state 0]
877 set s1 [string index $new_state 1]
879 if {[catch {set info $file_states($path)}]} {
881 set icon n[incr next_icon_id]
883 set state [lindex $info 0]
884 set icon [lindex $info 1]
888 set s0 [string index $state 0]
889 } elseif {$s0 == {*}} {
894 set s1 [string index $state 1]
895 } elseif {$s1 == {*}} {
899 set file_states($path) [list $s0$s1 $icon]
903 proc display_file {path state} {
904 global ui_index ui_other
905 global file_states file_lists status_active
907 set old_m [merge_state $path $state]
908 if {$status_active} return
910 set s $file_states($path)
911 set new_m [lindex $s 0]
912 set new_w [mapcol $new_m $path]
913 set old_w [mapcol $old_m $path]
914 set new_icon [mapicon $new_m $path]
916 if {$new_w != $old_w} {
917 set lno [lsearch -sorted $file_lists($old_w) $path]
920 $old_w conf -state normal
921 $old_w delete $lno.0 [expr $lno + 1].0
922 $old_w conf -state disabled
925 lappend file_lists($new_w) $path
926 set file_lists($new_w) [lsort $file_lists($new_w)]
927 set lno [lsearch -sorted $file_lists($new_w) $path]
929 $new_w conf -state normal
930 $new_w image create $lno.0 \
931 -align center -padx 5 -pady 1 \
932 -name [lindex $s 1] \
934 $new_w insert $lno.1 "[escape_path $path]\n"
935 $new_w conf -state disabled
936 } elseif {$new_icon != [mapicon $old_m $path]} {
937 $new_w conf -state normal
938 $new_w image conf [lindex $s 1] -image $new_icon
939 $new_w conf -state disabled
943 proc display_all_files {} {
944 global ui_index ui_other file_states file_lists
946 $ui_index conf -state normal
947 $ui_other conf -state normal
949 $ui_index delete 0.0 end
950 $ui_other delete 0.0 end
952 array unset file_lists
953 foreach path [lsort [array names file_states]] {
954 set s $file_states($path)
956 set w [mapcol $m $path]
957 lappend file_lists($w) $path
958 $w image create end \
959 -align center -padx 5 -pady 1 \
960 -name [lindex $s 1] \
961 -image [mapicon $m $path]
962 $w insert end "[escape_path $path]\n"
965 $ui_index conf -state disabled
966 $ui_other conf -state disabled
969 proc with_update_index {body} {
970 global update_index_fd
972 if {$update_index_fd == {}} {
973 if {![lock_index update]} return
974 set update_index_fd [open \
975 "| git update-index --add --remove -z --stdin" \
977 fconfigure $update_index_fd -translation binary
979 close $update_index_fd
980 set update_index_fd {}
987 proc update_index {path} {
988 global update_index_fd
990 if {$update_index_fd == {}} {
991 error {not in with_update_index}
993 puts -nonewline $update_index_fd "$path\0"
997 proc toggle_mode {path} {
998 global file_states ui_fname_value
1000 set s $file_states($path)
1013 with_update_index {update_index $path}
1014 display_file $path $new
1015 if {$ui_fname_value == $path} {
1020 ######################################################################
1022 ## remote management
1024 proc load_all_remotes {} {
1025 global gitdir all_remotes repo_config
1027 set all_remotes [list]
1028 set rm_dir [file join $gitdir remotes]
1029 if {[file isdirectory $rm_dir]} {
1030 set all_remotes [concat $all_remotes [glob \
1034 -directory $rm_dir *]]
1037 foreach line [array names repo_config remote.*.url] {
1038 if {[regexp ^remote\.(.*)\.url\$ $line line name]} {
1039 lappend all_remotes $name
1043 set all_remotes [lsort -unique $all_remotes]
1046 proc populate_remote_menu {m pfx op} {
1047 global all_remotes mainfont
1049 foreach remote $all_remotes {
1050 $m add command -label "$pfx $remote..." \
1051 -command [list $op $remote] \
1056 proc populate_pull_menu {m} {
1057 global gitdir repo_config all_remotes mainfont disable_on_lock
1059 foreach remote $all_remotes {
1061 if {[array get repo_config remote.$remote.url] != {}} {
1062 if {[array get repo_config remote.$remote.fetch] != {}} {
1063 regexp {^([^:]+):} \
1064 [lindex $repo_config(remote.$remote.fetch) 0] \
1069 set fd [open [file join $gitdir remotes $remote] r]
1070 while {[gets $fd line] >= 0} {
1071 if {[regexp {^Pull:[ \t]*([^:]+):} $line line rb]} {
1080 regsub ^refs/heads/ $rb {} rb_short
1081 if {$rb_short != {}} {
1083 -label "Branch $rb_short from $remote..." \
1084 -command [list pull_remote $remote $rb] \
1086 lappend disable_on_lock \
1087 [list $m entryconf [$m index last] -state]
1092 ######################################################################
1097 #define mask_width 14
1098 #define mask_height 15
1099 static unsigned char mask_bits[] = {
1100 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f,
1101 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f,
1102 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x1f};
1105 image create bitmap file_plain -background white -foreground black -data {
1106 #define plain_width 14
1107 #define plain_height 15
1108 static unsigned char plain_bits[] = {
1109 0xfe, 0x01, 0x02, 0x03, 0x02, 0x05, 0x02, 0x09, 0x02, 0x1f, 0x02, 0x10,
1110 0x02, 0x10, 0x02, 0x10, 0x02, 0x10, 0x02, 0x10, 0x02, 0x10, 0x02, 0x10,
1111 0x02, 0x10, 0x02, 0x10, 0xfe, 0x1f};
1112 } -maskdata $filemask
1114 image create bitmap file_mod -background white -foreground blue -data {
1115 #define mod_width 14
1116 #define mod_height 15
1117 static unsigned char mod_bits[] = {
1118 0xfe, 0x01, 0x02, 0x03, 0x7a, 0x05, 0x02, 0x09, 0x7a, 0x1f, 0x02, 0x10,
1119 0xfa, 0x17, 0x02, 0x10, 0xfa, 0x17, 0x02, 0x10, 0xfa, 0x17, 0x02, 0x10,
1120 0xfa, 0x17, 0x02, 0x10, 0xfe, 0x1f};
1121 } -maskdata $filemask
1123 image create bitmap file_fulltick -background white -foreground "#007000" -data {
1124 #define file_fulltick_width 14
1125 #define file_fulltick_height 15
1126 static unsigned char file_fulltick_bits[] = {
1127 0xfe, 0x01, 0x02, 0x1a, 0x02, 0x0c, 0x02, 0x0c, 0x02, 0x16, 0x02, 0x16,
1128 0x02, 0x13, 0x00, 0x13, 0x86, 0x11, 0x8c, 0x11, 0xd8, 0x10, 0xf2, 0x10,
1129 0x62, 0x10, 0x02, 0x10, 0xfe, 0x1f};
1130 } -maskdata $filemask
1132 image create bitmap file_parttick -background white -foreground "#005050" -data {
1133 #define parttick_width 14
1134 #define parttick_height 15
1135 static unsigned char parttick_bits[] = {
1136 0xfe, 0x01, 0x02, 0x03, 0x7a, 0x05, 0x02, 0x09, 0x7a, 0x1f, 0x02, 0x10,
1137 0x7a, 0x14, 0x02, 0x16, 0x02, 0x13, 0x8a, 0x11, 0xda, 0x10, 0x72, 0x10,
1138 0x22, 0x10, 0x02, 0x10, 0xfe, 0x1f};
1139 } -maskdata $filemask
1141 image create bitmap file_question -background white -foreground black -data {
1142 #define file_question_width 14
1143 #define file_question_height 15
1144 static unsigned char file_question_bits[] = {
1145 0xfe, 0x01, 0x02, 0x02, 0xe2, 0x04, 0xf2, 0x09, 0x1a, 0x1b, 0x0a, 0x13,
1146 0x82, 0x11, 0xc2, 0x10, 0x62, 0x10, 0x62, 0x10, 0x02, 0x10, 0x62, 0x10,
1147 0x62, 0x10, 0x02, 0x10, 0xfe, 0x1f};
1148 } -maskdata $filemask
1150 image create bitmap file_removed -background white -foreground red -data {
1151 #define file_removed_width 14
1152 #define file_removed_height 15
1153 static unsigned char file_removed_bits[] = {
1154 0xfe, 0x01, 0x02, 0x03, 0x02, 0x05, 0x02, 0x09, 0x02, 0x1f, 0x02, 0x10,
1155 0x1a, 0x16, 0x32, 0x13, 0xe2, 0x11, 0xc2, 0x10, 0xe2, 0x11, 0x32, 0x13,
1156 0x1a, 0x16, 0x02, 0x10, 0xfe, 0x1f};
1157 } -maskdata $filemask
1159 image create bitmap file_merge -background white -foreground blue -data {
1160 #define file_merge_width 14
1161 #define file_merge_height 15
1162 static unsigned char file_merge_bits[] = {
1163 0xfe, 0x01, 0x02, 0x03, 0x62, 0x05, 0x62, 0x09, 0x62, 0x1f, 0x62, 0x10,
1164 0xfa, 0x11, 0xf2, 0x10, 0x62, 0x10, 0x02, 0x10, 0xfa, 0x17, 0x02, 0x10,
1165 0xfa, 0x17, 0x02, 0x10, 0xfe, 0x1f};
1166 } -maskdata $filemask
1168 set ui_index .vpane.files.index.list
1169 set ui_other .vpane.files.other.list
1170 set max_status_desc 0
1172 {__ i plain "Unmodified"}
1173 {_M i mod "Modified"}
1174 {M_ i fulltick "Checked in"}
1175 {MM i parttick "Partially included"}
1177 {_O o plain "Untracked"}
1178 {A_ o fulltick "Added"}
1179 {AM o parttick "Partially added"}
1180 {AD o question "Added (but now gone)"}
1182 {_D i question "Missing"}
1183 {D_ i removed "Removed"}
1184 {DD i removed "Removed"}
1185 {DO i removed "Removed (still exists)"}
1187 {UM i merge "Merge conflicts"}
1188 {U_ i merge "Merge conflicts"}
1190 if {$max_status_desc < [string length [lindex $i 3]]} {
1191 set max_status_desc [string length [lindex $i 3]]
1193 if {[lindex $i 1] == {i}} {
1194 set all_cols([lindex $i 0]) $ui_index
1196 set all_cols([lindex $i 0]) $ui_other
1198 set all_icons([lindex $i 0]) file_[lindex $i 2]
1199 set all_descs([lindex $i 0]) [lindex $i 3]
1203 ######################################################################
1207 proc error_popup {msg} {
1214 proc show_msg {w top msg} {
1215 global gitdir appname mainfont
1217 message $w.m -text $msg -justify left -aspect 400
1218 pack $w.m -side top -fill x -padx 5 -pady 10
1219 button $w.ok -text OK \
1222 -command "destroy $top"
1223 pack $w.ok -side bottom
1224 bind $top <Visibility> "grab $top; focus $top"
1225 bind $top <Key-Return> "destroy $top"
1226 wm title $w "$appname ([lindex [file split \
1227 [file normalize [file dirname $gitdir]]] \
1232 proc hook_failed_popup {hook msg} {
1233 global gitdir mainfont difffont appname
1240 label $w.m.l1 -text "$hook hook failed:" \
1243 -font [concat $mainfont bold]
1245 -background white -borderwidth 1 \
1247 -width 80 -height 10 \
1249 -yscrollcommand [list $w.m.sby set]
1251 -text {You must correct the above errors before committing.} \
1254 -font [concat $mainfont bold]
1255 scrollbar $w.m.sby -command [list $w.m.t yview]
1256 pack $w.m.l1 -side top -fill x
1257 pack $w.m.l2 -side bottom -fill x
1258 pack $w.m.sby -side right -fill y
1259 pack $w.m.t -side left -fill both -expand 1
1260 pack $w.m -side top -fill both -expand 1 -padx 5 -pady 10
1262 $w.m.t insert 1.0 $msg
1263 $w.m.t conf -state disabled
1265 button $w.ok -text OK \
1268 -command "destroy $w"
1269 pack $w.ok -side bottom
1271 bind $w <Visibility> "grab $w; focus $w"
1272 bind $w <Key-Return> "destroy $w"
1273 wm title $w "$appname ([lindex [file split \
1274 [file normalize [file dirname $gitdir]]] \
1279 set next_console_id 0
1281 proc new_console {short_title long_title} {
1282 global next_console_id console_data
1283 set w .console[incr next_console_id]
1284 set console_data($w) [list $short_title $long_title]
1285 return [console_init $w]
1288 proc console_init {w} {
1289 global console_cr console_data
1290 global gitdir appname mainfont difffont
1292 set console_cr($w) 1.0
1295 label $w.m.l1 -text "[lindex $console_data($w) 1]:" \
1298 -font [concat $mainfont bold]
1300 -background white -borderwidth 1 \
1302 -width 80 -height 10 \
1305 -yscrollcommand [list $w.m.sby set]
1306 label $w.m.s -anchor w \
1308 -font [concat $mainfont bold]
1309 scrollbar $w.m.sby -command [list $w.m.t yview]
1310 pack $w.m.l1 -side top -fill x
1311 pack $w.m.s -side bottom -fill x
1312 pack $w.m.sby -side right -fill y
1313 pack $w.m.t -side left -fill both -expand 1
1314 pack $w.m -side top -fill both -expand 1 -padx 5 -pady 10
1316 button $w.ok -text {Running...} \
1320 -command "destroy $w"
1321 pack $w.ok -side bottom
1323 bind $w <Visibility> "focus $w"
1324 wm title $w "$appname ([lindex [file split \
1325 [file normalize [file dirname $gitdir]]] \
1326 end]): [lindex $console_data($w) 0]"
1330 proc console_exec {w cmd {after {}}} {
1333 # -- Windows tosses the enviroment when we exec our child.
1334 # But most users need that so we have to relogin. :-(
1336 if {$tcl_platform(platform) == {windows}} {
1337 set cmd [list sh --login -c "cd \"[pwd]\" && [join $cmd { }]"]
1340 # -- Tcl won't
let us redirect both stdout and stderr to
1341 # the same pipe. So pass it through cat...
1343 set cmd
[concat |
$cmd |
& cat]
1345 set fd_f
[open
$cmd r
]
1346 fconfigure
$fd_f -blocking 0 -translation binary
1347 fileevent
$fd_f readable
[list console_read
$w $fd_f $after]
1350 proc console_read
{w fd after
} {
1351 global console_cr console_data
1355 if {![winfo exists
$w]} {console_init
$w}
1356 $w.m.t conf
-state normal
1358 set n
[string length
$buf]
1360 set cr
[string first
"\r" $buf $c]
1361 set lf
[string first
"\n" $buf $c]
1362 if {$cr < 0} {set cr
[expr $n + 1]}
1363 if {$lf < 0} {set lf
[expr $n + 1]}
1366 $w.m.t insert end
[string range
$buf $c $lf]
1367 set console_cr
($w) [$w.m.t index
{end
-1c}]
1371 $w.m.t delete
$console_cr($w) end
1372 $w.m.t insert end
"\n"
1373 $w.m.t insert end
[string range
$buf $c $cr]
1378 $w.m.t conf
-state disabled
1382 fconfigure
$fd -blocking 1
1384 if {[catch
{close
$fd}]} {
1385 if {![winfo exists
$w]} {console_init
$w}
1386 $w.m.s conf
-background red
-text {Error
: Command Failed
}
1387 $w.ok conf
-text Close
1388 $w.ok conf
-state normal
1390 } elseif
{[winfo exists
$w]} {
1391 $w.m.s conf
-background green
-text {Success
}
1392 $w.ok conf
-text Close
1393 $w.ok conf
-state normal
1396 array
unset console_cr
$w
1397 array
unset console_data
$w
1399 uplevel
#0 $after $ok
1403 fconfigure
$fd -blocking 0
1406 ######################################################################
1410 set starting_gitk_msg
{Please
wait... Starting gitk...
}
1413 global tcl_platform ui_status_value starting_gitk_msg
1415 set ui_status_value
$starting_gitk_msg
1417 if {$ui_status_value == $starting_gitk_msg} {
1418 set ui_status_value
{Ready.
}
1422 if {$tcl_platform(platform
) == {windows
}} {
1430 set w
[new_console
"repack" "Repacking the object database"]
1431 set cmd
[list git repack
]
1434 console_exec
$w $cmd
1438 global gitdir ui_comm
1440 set save
[file join $gitdir GITGUI_MSG
]
1441 set msg
[string trim
[$ui_comm get
0.0 end
]]
1442 if {[$ui_comm edit modified
] && $msg != {}} {
1444 set fd
[open
$save w
]
1445 puts
$fd [string trim
[$ui_comm get
0.0 end
]]
1448 } elseif
{$msg == {} && [file exists
$save]} {
1460 proc do_include_all
{} {
1461 global update_active ui_status_value
1463 if {$update_active ||
![lock_index begin-update
]} return
1466 set ui_status_value
{Including all modified files...
}
1469 foreach path
[array names file_states
] {
1470 set s
$file_states($path)
1476 _D
{toggle_mode
$path}
1481 set ui_status_value
{Ready.
}
1485 proc do_signoff
{} {
1486 global ui_comm GIT_COMMITTER_IDENT
1488 if {$GIT_COMMITTER_IDENT == {}} {
1489 if {[catch
{set me
[exec git var GIT_COMMITTER_IDENT
]} err
]} {
1490 error_popup
"Unable to obtain your identity:\n$err"
1493 if {![regexp
{^
(.
*) [0-9]+ [-+0-9]+$
} \
1494 $me me GIT_COMMITTER_IDENT
]} {
1495 error_popup
"Invalid GIT_COMMITTER_IDENT:\n$me"
1500 set str
"Signed-off-by: $GIT_COMMITTER_IDENT"
1501 if {[$ui_comm get
{end
-1c linestart
} {end
-1c}] != $str} {
1502 $ui_comm edit separator
1503 $ui_comm insert end
"\n$str"
1504 $ui_comm edit separator
1509 proc do_amend_last
{} {
1517 # shift == 1: left click
1519 proc click
{w x y
shift wx wy
} {
1520 global ui_index ui_other file_lists
1522 set pos
[split [$w index @
$x,$y] .
]
1523 set lno
[lindex
$pos 0]
1524 set col [lindex
$pos 1]
1525 set path
[lindex
$file_lists($w) [expr $lno - 1]]
1526 if {$path == {}} return
1528 if {$col > 0 && $shift == 1} {
1529 show_diff
$path $w $lno
1533 proc unclick
{w x y
} {
1536 set pos
[split [$w index @
$x,$y] .
]
1537 set lno
[lindex
$pos 0]
1538 set col [lindex
$pos 1]
1539 set path
[lindex
$file_lists($w) [expr $lno - 1]]
1540 if {$path == {}} return
1547 ######################################################################
1551 set mainfont
{Helvetica
10}
1552 set difffont
{Courier
10}
1553 set maincursor
[. cget
-cursor]
1555 switch
-glob -- "$tcl_platform(platform),$tcl_platform(os)" {
1556 windows
,* {set M1B Control
; set M1T Ctrl
}
1557 unix
,Darwin
{set M1B M1
; set M1T Cmd
}
1558 default
{set M1B M1
; set M1T M1
}
1562 menu .mbar
-tearoff 0
1563 .mbar add cascade
-label Project
-menu .mbar.project
1564 .mbar add cascade
-label Edit
-menu .mbar.edit
1565 .mbar add cascade
-label Commit
-menu .mbar.commit
1566 .mbar add cascade
-label Fetch
-menu .mbar.fetch
1567 .mbar add cascade
-label Pull
-menu .mbar.pull
1568 .mbar add cascade
-label Push
-menu .mbar.push
1569 .mbar add cascade
-label Options
-menu .mbar.options
1570 . configure
-menu .mbar
1574 .mbar.project add
command -label Visualize \
1577 .mbar.project add
command -label {Repack Database
} \
1578 -command do_repack \
1580 .mbar.project add
command -label Quit \
1582 -accelerator $M1T-Q \
1588 .mbar.edit add
command -label Undo \
1589 -command {catch
{[focus
] edit undo
}} \
1590 -accelerator $M1T-Z \
1592 .mbar.edit add
command -label Redo \
1593 -command {catch
{[focus
] edit redo
}} \
1594 -accelerator $M1T-Y \
1596 .mbar.edit add separator
1597 .mbar.edit add
command -label Cut \
1598 -command {catch
{tk_textCut
[focus
]}} \
1599 -accelerator $M1T-X \
1601 .mbar.edit add
command -label Copy \
1602 -command {catch
{tk_textCopy
[focus
]}} \
1603 -accelerator $M1T-C \
1605 .mbar.edit add
command -label Paste \
1606 -command {catch
{tk_textPaste
[focus
]; [focus
] see insert
}} \
1607 -accelerator $M1T-V \
1609 .mbar.edit add
command -label Delete \
1610 -command {catch
{[focus
] delete sel.first sel.last
}} \
1613 .mbar.edit add separator
1614 .mbar.edit add
command -label {Select All
} \
1615 -command {catch
{[focus
] tag add sel
0.0 end
}} \
1616 -accelerator $M1T-A \
1621 .mbar.commit add
command -label Rescan \
1622 -command do_rescan \
1625 lappend disable_on_lock \
1626 [list .mbar.commit entryconf
[.mbar.commit index last
] -state]
1627 .mbar.commit add
command -label {Amend Last Commit
} \
1628 -command do_amend_last \
1630 lappend disable_on_lock \
1631 [list .mbar.commit entryconf
[.mbar.commit index last
] -state]
1632 .mbar.commit add
command -label {Include All Files
} \
1633 -command do_include_all \
1634 -accelerator $M1T-I \
1636 lappend disable_on_lock \
1637 [list .mbar.commit entryconf
[.mbar.commit index last
] -state]
1638 .mbar.commit add
command -label {Sign Off
} \
1639 -command do_signoff \
1640 -accelerator $M1T-S \
1642 .mbar.commit add
command -label Commit \
1643 -command do_commit \
1644 -accelerator $M1T-Return \
1646 lappend disable_on_lock \
1647 [list .mbar.commit entryconf
[.mbar.commit index last
] -state]
1660 .mbar.options add checkbutton \
1661 -label {Trust File Modification Timestamps
} \
1664 -variable cfg_trust_mtime
1666 # -- Main Window Layout
1667 panedwindow .vpane
-orient vertical
1668 panedwindow .vpane.files
-orient horizontal
1669 .vpane add .vpane.files
-sticky nsew
-height 100 -width 400
1670 pack .vpane
-anchor n
-side top
-fill both
-expand 1
1672 # -- Index File List
1673 frame .vpane.files.index
-height 100 -width 400
1674 label .vpane.files.index.title
-text {Modified Files
} \
1677 text
$ui_index -background white
-borderwidth 0 \
1678 -width 40 -height 10 \
1680 -yscrollcommand {.vpane.files.index.sb
set} \
1681 -cursor $maincursor \
1683 scrollbar .vpane.files.index.sb
-command [list
$ui_index yview
]
1684 pack .vpane.files.index.title
-side top
-fill x
1685 pack .vpane.files.index.sb
-side right
-fill y
1686 pack
$ui_index -side left
-fill both
-expand 1
1687 .vpane.files add .vpane.files.index
-sticky nsew
1689 # -- Other (Add) File List
1690 frame .vpane.files.other
-height 100 -width 100
1691 label .vpane.files.other.title
-text {Untracked Files
} \
1694 text
$ui_other -background white
-borderwidth 0 \
1695 -width 40 -height 10 \
1697 -yscrollcommand {.vpane.files.other.sb
set} \
1698 -cursor $maincursor \
1700 scrollbar .vpane.files.other.sb
-command [list
$ui_other yview
]
1701 pack .vpane.files.other.title
-side top
-fill x
1702 pack .vpane.files.other.sb
-side right
-fill y
1703 pack
$ui_other -side left
-fill both
-expand 1
1704 .vpane.files add .vpane.files.other
-sticky nsew
1706 $ui_index tag conf in_diff
-font [concat
$mainfont bold
]
1707 $ui_other tag conf in_diff
-font [concat
$mainfont bold
]
1709 # -- Diff and Commit Area
1710 frame .vpane.lower
-height 400 -width 400
1711 frame .vpane.lower.commarea
1712 frame .vpane.lower.
diff -relief sunken
-borderwidth 1
1713 pack .vpane.lower.commarea
-side top
-fill x
1714 pack .vpane.lower.
diff -side bottom
-fill both
-expand 1
1715 .vpane add .vpane.lower
-stick nsew
1717 # -- Commit Area Buttons
1718 frame .vpane.lower.commarea.buttons
1719 label .vpane.lower.commarea.buttons.l
-text {} \
1723 pack .vpane.lower.commarea.buttons.l
-side top
-fill x
1724 pack .vpane.lower.commarea.buttons
-side left
-fill y
1726 button .vpane.lower.commarea.buttons.rescan
-text {Rescan
} \
1727 -command do_rescan \
1729 pack .vpane.lower.commarea.buttons.rescan
-side top
-fill x
1730 lappend disable_on_lock
{.vpane.lower.commarea.buttons.rescan conf
-state}
1732 button .vpane.lower.commarea.buttons.amend
-text {Amend Last
} \
1733 -command do_amend_last \
1735 pack .vpane.lower.commarea.buttons.amend
-side top
-fill x
1736 lappend disable_on_lock
{.vpane.lower.commarea.buttons.amend conf
-state}
1738 button .vpane.lower.commarea.buttons.incall
-text {Include All
} \
1739 -command do_include_all \
1741 pack .vpane.lower.commarea.buttons.incall
-side top
-fill x
1742 lappend disable_on_lock
{.vpane.lower.commarea.buttons.incall conf
-state}
1744 button .vpane.lower.commarea.buttons.signoff
-text {Sign Off
} \
1745 -command do_signoff \
1747 pack .vpane.lower.commarea.buttons.signoff
-side top
-fill x
1749 button .vpane.lower.commarea.buttons.commit
-text {Commit
} \
1750 -command do_commit \
1752 pack .vpane.lower.commarea.buttons.commit
-side top
-fill x
1753 lappend disable_on_lock
{.vpane.lower.commarea.buttons.commit conf
-state}
1755 # -- Commit Message Buffer
1756 frame .vpane.lower.commarea.buffer
1757 set ui_comm .vpane.lower.commarea.buffer.t
1758 set ui_coml .vpane.lower.commarea.buffer.l
1759 label
$ui_coml -text {Commit Message
:} \
1763 trace add variable commit_type
write {uplevel
#0 {
1764 switch
-glob $commit_type \
1765 initial
{$ui_coml conf
-text {Initial Commit Message
:}} \
1766 amend
{$ui_coml conf
-text {Amended Commit Message
:}} \
1767 merge
{$ui_coml conf
-text {Merge Commit Message
:}} \
1768 * {$ui_coml conf
-text {Commit Message
:}}
1770 text
$ui_comm -background white
-borderwidth 1 \
1773 -autoseparators true \
1775 -width 75 -height 9 -wrap none \
1777 -yscrollcommand {.vpane.lower.commarea.buffer.sby
set} \
1779 scrollbar .vpane.lower.commarea.buffer.sby
-command [list
$ui_comm yview
]
1780 pack
$ui_coml -side top
-fill x
1781 pack .vpane.lower.commarea.buffer.sby
-side right
-fill y
1782 pack
$ui_comm -side left
-fill y
1783 pack .vpane.lower.commarea.buffer
-side left
-fill y
1786 set ui_fname_value
{}
1787 set ui_fstatus_value
{}
1788 frame .vpane.lower.
diff.header
-background orange
1789 label .vpane.lower.
diff.header.l1
-text {File
:} \
1790 -background orange \
1792 label .vpane.lower.
diff.header.l2
-textvariable ui_fname_value \
1793 -background orange \
1797 label .vpane.lower.
diff.header.l3
-text {Status
:} \
1798 -background orange \
1800 label .vpane.lower.
diff.header.l4
-textvariable ui_fstatus_value \
1801 -background orange \
1802 -width $max_status_desc \
1806 pack .vpane.lower.
diff.header.l1
-side left
1807 pack .vpane.lower.
diff.header.l2
-side left
-fill x
1808 pack .vpane.lower.
diff.header.l4
-side right
1809 pack .vpane.lower.
diff.header.l3
-side right
1812 frame .vpane.lower.
diff.body
1813 set ui_diff .vpane.lower.
diff.body.t
1814 text
$ui_diff -background white
-borderwidth 0 \
1815 -width 80 -height 15 -wrap none \
1817 -xscrollcommand {.vpane.lower.
diff.body.sbx
set} \
1818 -yscrollcommand {.vpane.lower.
diff.body.sby
set} \
1819 -cursor $maincursor \
1821 scrollbar .vpane.lower.
diff.body.sbx
-orient horizontal \
1822 -command [list
$ui_diff xview
]
1823 scrollbar .vpane.lower.
diff.body.sby
-orient vertical \
1824 -command [list
$ui_diff yview
]
1825 pack .vpane.lower.
diff.body.sbx
-side bottom
-fill x
1826 pack .vpane.lower.
diff.body.sby
-side right
-fill y
1827 pack
$ui_diff -side left
-fill both
-expand 1
1828 pack .vpane.lower.
diff.header
-side top
-fill x
1829 pack .vpane.lower.
diff.body
-side bottom
-fill both
-expand 1
1831 $ui_diff tag conf dm
-foreground red
1832 $ui_diff tag conf dp
-foreground blue
1833 $ui_diff tag conf da
-font [concat
$difffont bold
]
1834 $ui_diff tag conf di
-foreground "#00a000"
1835 $ui_diff tag conf dni
-foreground "#a000a0"
1836 $ui_diff tag conf bold
-font [concat
$difffont bold
]
1839 set ui_status_value
{Initializing...
}
1840 label .status
-textvariable ui_status_value \
1846 pack .status
-anchor w
-side bottom
-fill x
1850 wm geometry .
[lindex
$repo_config(gui.geometry
) 0 0]
1851 eval .vpane sash place
0 [lindex
$repo_config(gui.geometry
) 0 1]
1852 eval .vpane.files sash place
0 [lindex
$repo_config(gui.geometry
) 0 2]
1856 bind $ui_comm <$M1B-Key-Return> {do_commit
;break}
1857 bind $ui_comm <$M1B-Key-i> {do_include_all
;break}
1858 bind $ui_comm <$M1B-Key-I> {do_include_all
;break}
1859 bind $ui_comm <$M1B-Key-x> {tk_textCut
%W
;break}
1860 bind $ui_comm <$M1B-Key-X> {tk_textCut
%W
;break}
1861 bind $ui_comm <$M1B-Key-c> {tk_textCopy
%W
;break}
1862 bind $ui_comm <$M1B-Key-C> {tk_textCopy
%W
;break}
1863 bind $ui_comm <$M1B-Key-v> {tk_textPaste
%W
; %W see insert
; break}
1864 bind $ui_comm <$M1B-Key-V> {tk_textPaste
%W
; %W see insert
; break}
1865 bind $ui_comm <$M1B-Key-a> {%W tag add sel
0.0 end
;break}
1866 bind $ui_comm <$M1B-Key-A> {%W tag add sel
0.0 end
;break}
1868 bind $ui_diff <$M1B-Key-x> {tk_textCopy
%W
;break}
1869 bind $ui_diff <$M1B-Key-X> {tk_textCopy
%W
;break}
1870 bind $ui_diff <$M1B-Key-c> {tk_textCopy
%W
;break}
1871 bind $ui_diff <$M1B-Key-C> {tk_textCopy
%W
;break}
1872 bind $ui_diff <$M1B-Key-v> {break}
1873 bind $ui_diff <$M1B-Key-V> {break}
1874 bind $ui_diff <$M1B-Key-a> {%W tag add sel
0.0 end
;break}
1875 bind $ui_diff <$M1B-Key-A> {%W tag add sel
0.0 end
;break}
1876 bind $ui_diff <Key-Up
> {catch
{%W yview scroll
-1 units
};break}
1877 bind $ui_diff <Key-Down
> {catch
{%W yview scroll
1 units
};break}
1878 bind $ui_diff <Key-Left
> {catch
{%W xview scroll
-1 units
};break}
1879 bind $ui_diff <Key-Right
> {catch
{%W xview scroll
1 units
};break}
1881 bind .
<Destroy
> do_quit
1882 bind all
<Key-F5
> do_rescan
1883 bind all
<$M1B-Key-r> do_rescan
1884 bind all
<$M1B-Key-R> do_rescan
1885 bind .
<$M1B-Key-s> do_signoff
1886 bind .
<$M1B-Key-S> do_signoff
1887 bind .
<$M1B-Key-i> do_include_all
1888 bind .
<$M1B-Key-I> do_include_all
1889 bind .
<$M1B-Key-Return> do_commit
1890 bind all
<$M1B-Key-q> do_quit
1891 bind all
<$M1B-Key-Q> do_quit
1892 bind all
<$M1B-Key-w> {destroy
[winfo toplevel
%W
]}
1893 bind all
<$M1B-Key-W> {destroy
[winfo toplevel
%W
]}
1894 foreach i
[list
$ui_index $ui_other] {
1895 bind $i <Button-1
> {click
%W
%x
%y
1 %X
%Y
; break}
1896 bind $i <Button-3
> {click
%W
%x
%y
3 %X
%Y
; break}
1897 bind $i <ButtonRelease-1
> {unclick
%W
%x
%y
; break}
1901 wm title .
"$appname ([file normalize [file dirname $gitdir]])"
1902 focus
-force $ui_comm
1904 populate_remote_menu .mbar.fetch From fetch_from
1905 populate_remote_menu .mbar.push To push_to
1906 populate_pull_menu .mbar.pull