X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=git-gui.sh;h=4617f29c26726c2cd438f160be21a8422e66b352;hb=2473543caabe63a9787e7ac42765c8f7169d7197;hp=88d1025dd028dfc5d0dd8ee169eebad95a5e6ddf;hpb=ed7b603381a57f706d758cf5a2f2ce604ef8c825;p=git.git diff --git a/git-gui.sh b/git-gui.sh index 88d1025dd..4617f29c2 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -10,8 +10,8 @@ exec wish "$argv0" -- "$@" set appvers {@@GITGUI_VERSION@@} -set copyright [encoding convertfrom utf-8 { -Copyright © 2006, 2007 Shawn Pearce, et. al. +set copyright [string map [list (c) \u00a9] { +Copyright (c) 2006-2010 Shawn Pearce, et. al. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -38,7 +38,7 @@ if {[catch {package require Tcl 8.4} err] tk_messageBox \ -icon error \ -type ok \ - -title [mc "git-gui: fatal error"] \ + -title "git-gui: fatal error" \ -message $err exit 1 } @@ -121,11 +121,14 @@ unset oguimsg set _appname {Git Gui} set _gitdir {} +set _gitworktree {} +set _isbare {} set _gitexec {} set _githtmldir {} set _reponame {} set _iscygwin {} set _search_path {} +set _shellpath {@@SHELL_PATH@@} set _trace [lsearch -exact $argv --trace] if {$_trace >= 0} { @@ -135,6 +138,18 @@ if {$_trace >= 0} { set _trace 0 } +proc shellpath {} { + global _shellpath env + if {[string match @@* $_shellpath]} { + if {[info exists env(SHELL)]} { + return $env(SHELL) + } else { + return /bin/sh + } + } + return $_shellpath +} + proc appname {} { global _appname return $_appname @@ -267,6 +282,17 @@ proc is_config_true {name} { } } +proc is_config_false {name} { + global repo_config + if {[catch {set v $repo_config($name)}]} { + return 0 + } elseif {$v eq {false} || $v eq {0} || $v eq {no}} { + return 1 + } else { + return 0 + } +} + proc get_config {name} { global repo_config if {[catch {set v $repo_config($name)}]} { @@ -276,6 +302,32 @@ proc get_config {name} { } } +proc is_bare {} { + global _isbare + global _gitdir + global _gitworktree + + if {$_isbare eq {}} { + if {[catch { + set _bare [git rev-parse --is-bare-repository] + switch -- $_bare { + true { set _isbare 1 } + false { set _isbare 0} + default { throw } + } + }]} { + if {[is_config_true core.bare] + || ($_gitworktree eq {} + && [lindex [file split $_gitdir] end] ne {.git})} { + set _isbare 1 + } else { + set _isbare 0 + } + } + } + return $_isbare +} + ###################################################################### ## ## handy utils @@ -295,6 +347,8 @@ proc _trace_exec {cmd} { puts stderr $d } +#'" fix poor old emacs font-lock mode + proc _git_cmd {name} { global _git_cmd_path @@ -388,6 +442,9 @@ proc _lappend_nice {cmd_var} { if {![info exists _nice]} { set _nice [_which nice] + if {[catch {exec $_nice git version}]} { + set _nice {} + } } if {$_nice ne {}} { lappend cmd $_nice @@ -606,6 +663,7 @@ proc rmsel_tag {text} { return $text } +wm withdraw . set root_exists 0 bind . { bind . {} @@ -649,12 +707,17 @@ if {[is_Windows]} { ## config defaults set cursor_ptr arrow -font create font_diff -family Courier -size 10 font create font_ui -catch { - label .dummy - eval font configure font_ui [font actual [.dummy cget -font]] - destroy .dummy +if {[lsearch -exact [font names] TkDefaultFont] != -1} { + eval [linsert [font actual TkDefaultFont] 0 font configure font_ui] + eval [linsert [font actual TkFixedFont] 0 font create font_diff] +} else { + font create font_diff -family Courier -size 10 + catch { + label .dummy + eval font configure font_ui [font actual [.dummy cget -font]] + destroy .dummy + } } font create font_uiitalic @@ -669,6 +732,9 @@ foreach class {Button Checkbutton Entry Label } if {![is_MacOSX]} { option add *Menu.font font_ui + option add *Entry.borderWidth 1 startupFile + option add *Entry.relief sunken startupFile + option add *RadioButton.anchor w startupFile } unset class @@ -721,6 +787,18 @@ proc apply_config {} { font configure ${font}bold -weight bold font configure ${font}italic -slant italic } + + global use_ttk NS + set use_ttk 0 + set NS {} + if {$repo_config(gui.usettk)} { + set use_ttk [package vsatisfies [package provide Tk] 8.5] + if {$use_ttk} { + set NS ttk + bind [winfo class .] <> [list InitTheme] + pave_toplevel . + } + } } set default_config(branch.autosetupmerge) true @@ -734,6 +812,7 @@ set default_config(user.email) {} set default_config(gui.encoding) [encoding system] set default_config(gui.matchtrackingbranch) false +set default_config(gui.textconv) true set default_config(gui.pruneduringfetch) false set default_config(gui.trustmtime) false set default_config(gui.fastcopyblame) false @@ -747,6 +826,7 @@ set default_config(gui.fontui) [font configure font_ui] set default_config(gui.fontdiff) [font configure font_diff] # TODO: this option should be added to the git-config documentation set default_config(gui.maxfilesdisplayed) 5000 +set default_config(gui.usettk) 1 set font_descs { {fontui font_ui {mc "Main Font"}} {fontdiff font_diff {mc "Diff/Console Font"}} @@ -1074,6 +1154,8 @@ if {[catch { set _prefix {} }] && [catch { + # beware that from the .git dir this sets _gitdir to . + # and _prefix to the empty string set _gitdir [git rev-parse --git-dir] set _prefix [git rev-parse --show-prefix] } err]} { @@ -1082,6 +1164,14 @@ if {[catch { choose_repository::pick set picked 1 } + +# we expand the _gitdir when it's just a single dot (i.e. when we're being +# run from the .git dir itself) lest the routines to find the worktree +# get confused +if {$_gitdir eq "."} { + set _gitdir [pwd] +} + if {![file isdirectory $_gitdir] && [is_Cygwin]} { catch {set _gitdir [exec cygpath --windows $_gitdir]} } @@ -1090,25 +1180,44 @@ if {![file isdirectory $_gitdir]} { error_popup [strcat [mc "Git directory not found:"] "\n\n$_gitdir"] exit 1 } +# _gitdir exists, so try loading the config +load_config 0 +apply_config +# try to set work tree from environment, falling back to core.worktree +if {[catch { set _gitworktree $env(GIT_WORK_TREE) }]} { + set _gitworktree [get_config core.worktree] + if {$_gitworktree eq ""} { + set _gitworktree [file dirname [file normalize $_gitdir]] + } +} if {$_prefix ne {}} { - regsub -all {[^/]+/} $_prefix ../ cdup + if {$_gitworktree eq {}} { + regsub -all {[^/]+/} $_prefix ../ cdup + } else { + set cdup $_gitworktree + } if {[catch {cd $cdup} err]} { catch {wm withdraw .} error_popup [strcat [mc "Cannot move to top of working directory:"] "\n\n$err"] exit 1 } + set _gitworktree [pwd] unset cdup } elseif {![is_enabled bare]} { - if {[lindex [file split $_gitdir] end] ne {.git}} { + if {[is_bare]} { catch {wm withdraw .} - error_popup [strcat [mc "Cannot use funny .git directory:"] "\n\n$_gitdir"] + error_popup [strcat [mc "Cannot use bare repository:"] "\n\n$_gitdir"] exit 1 } - if {[catch {cd [file dirname $_gitdir]} err]} { + if {$_gitworktree eq {}} { + set _gitworktree [file dirname $_gitdir] + } + if {[catch {cd $_gitworktree} err]} { catch {wm withdraw .} - error_popup [strcat [mc "No working directory"] " [file dirname $_gitdir]:\n\n$err"] + error_popup [strcat [mc "No working directory"] " $_gitworktree:\n\n$err"] exit 1 } + set _gitworktree [pwd] } set _reponame [file split [file normalize $_gitdir]] if {[lindex $_reponame end] eq {.git}} { @@ -1117,6 +1226,9 @@ if {[lindex $_reponame end] eq {.git}} { set _reponame [lindex $_reponame end] } +set env(GIT_DIR) $_gitdir +set env(GIT_WORK_TREE) $_gitworktree + ###################################################################### ## ## global init @@ -1134,6 +1246,7 @@ set current_branch {} set is_detached 0 set current_diff_path {} set is_3way_diff 0 +set is_submodule_diff 0 set is_conflict_diff 0 set selected_commit_type new set diff_empty_count 0 @@ -1612,6 +1725,9 @@ proc merge_state {path new_state {head_info {}} {index_info {}}} { } elseif {$s0 ne {_} && [string index $state 0] eq {_} && $head_info eq {}} { set head_info $index_info + } elseif {$s0 eq {_} && [string index $state 0] ne {_}} { + set index_info $head_info + set head_info {} } set file_states($path) [list $s0$s1 $icon \ @@ -1794,15 +1910,6 @@ static unsigned char file_fulltick_bits[] = { 0x62, 0x10, 0x02, 0x10, 0xfe, 0x1f}; } -maskdata $filemask -image create bitmap file_parttick -background white -foreground "#005050" -data { -#define parttick_width 14 -#define parttick_height 15 -static unsigned char parttick_bits[] = { - 0xfe, 0x01, 0x02, 0x03, 0x7a, 0x05, 0x02, 0x09, 0x7a, 0x1f, 0x02, 0x10, - 0x7a, 0x14, 0x02, 0x16, 0x02, 0x13, 0x8a, 0x11, 0xda, 0x10, 0x72, 0x10, - 0x22, 0x10, 0x02, 0x10, 0xfe, 0x1f}; -} -maskdata $filemask - image create bitmap file_question -background white -foreground black -data { #define file_question_width 14 #define file_question_height 15 @@ -1843,7 +1950,7 @@ set ui_index .vpane.files.index.list set ui_workdir .vpane.files.workdir.list set all_icons(_$ui_index) file_plain -set all_icons(A$ui_index) file_fulltick +set all_icons(A$ui_index) file_plain set all_icons(M$ui_index) file_fulltick set all_icons(D$ui_index) file_removed set all_icons(U$ui_index) file_merge @@ -1919,7 +2026,10 @@ proc incr_font_size {font {amt 1}} { set starting_gitk_msg [mc "Starting gitk... please wait..."] -proc do_gitk {revs} { +proc do_gitk {revs {is_submodule false}} { + global current_diff_path file_states current_diff_side ui_index + global _gitdir _gitworktree + # -- Always start gitk through whatever we were loaded with. This # lets us bypass using shell process on Windows systems. # @@ -1930,23 +2040,78 @@ proc do_gitk {revs} { } else { global env - if {[info exists env(GIT_DIR)]} { - set old_GIT_DIR $env(GIT_DIR) + set pwd [pwd] + + if {!$is_submodule} { + if {![is_bare]} { + cd $_gitworktree + } } else { - set old_GIT_DIR {} + cd $current_diff_path + if {$revs eq {--}} { + set s $file_states($current_diff_path) + set old_sha1 {} + set new_sha1 {} + switch -glob -- [lindex $s 0] { + M_ { set old_sha1 [lindex [lindex $s 2] 1] } + _M { set old_sha1 [lindex [lindex $s 3] 1] } + MM { + if {$current_diff_side eq $ui_index} { + set old_sha1 [lindex [lindex $s 2] 1] + set new_sha1 [lindex [lindex $s 3] 1] + } else { + set old_sha1 [lindex [lindex $s 3] 1] + } + } + } + set revs $old_sha1...$new_sha1 + } + # GIT_DIR and GIT_WORK_TREE for the submodule are not the ones + # we've been using for the main repository, so unset them. + # TODO we could make life easier (start up faster?) for gitk + # by setting these to the appropriate values to allow gitk + # to skip the heuristics to find their proper value + unset env(GIT_DIR) + unset env(GIT_WORK_TREE) } + eval exec $cmd $revs "--" "--" & + + set env(GIT_DIR) $_gitdir + set env(GIT_WORK_TREE) $_gitworktree + cd $pwd + + ui_status $::starting_gitk_msg + after 10000 { + ui_ready $starting_gitk_msg + } + } +} + +proc do_git_gui {} { + global current_diff_path + + # -- Always start git gui through whatever we were loaded with. This + # lets us bypass using shell process on Windows systems. + # + set exe [list [_which git]] + if {$exe eq {}} { + error_popup [mc "Couldn't find git gui in PATH"] + } else { + global env + global _gitdir _gitworktree + + # see note in do_gitk about unsetting these vars when + # running tools in a submodule + unset env(GIT_DIR) + unset env(GIT_WORK_TREE) set pwd [pwd] - cd [file dirname [gitdir]] - set env(GIT_DIR) [file tail [gitdir]] + cd $current_diff_path - eval exec $cmd $revs & + eval exec $exe gui & - if {$old_GIT_DIR eq {}} { - unset env(GIT_DIR) - } else { - set env(GIT_DIR) $old_GIT_DIR - } + set env(GIT_DIR) $_gitdir + set env(GIT_WORK_TREE) $_gitworktree cd $pwd ui_status $::starting_gitk_msg @@ -1957,6 +2122,7 @@ proc do_gitk {revs} { } proc do_explore {} { + global _gitworktree set explorer {} if {[is_Cygwin] || [is_Windows]} { set explorer "explorer.exe" @@ -1966,7 +2132,7 @@ proc do_explore {} { # freedesktop.org-conforming system is our best shot set explorer "xdg-open" } - eval exec $explorer [list [file nativename [file dirname [gitdir]]]] & + eval exec $explorer [list [file nativename $_gitworktree]] & } set is_quitting 0 @@ -1982,7 +2148,7 @@ proc do_quit {{rc {1}}} { global ui_comm is_quitting repo_config commit_type global GITGUI_BCK_exists GITGUI_BCK_i global ui_comm_spell - global ret_code + global ret_code use_ttk if {$is_quitting} return set is_quitting 1 @@ -2040,8 +2206,13 @@ proc do_quit {{rc {1}}} { } set cfg_geometry [list] lappend cfg_geometry [wm geometry .] - lappend cfg_geometry [lindex [.vpane sash coord 0] 0] - lappend cfg_geometry [lindex [.vpane.files sash coord 0] 1] + if {$use_ttk} { + lappend cfg_geometry [.vpane sashpos 0] + lappend cfg_geometry [.vpane.files sashpos 0] + } else { + lappend cfg_geometry [lindex [.vpane sash coord 0] 0] + lappend cfg_geometry [lindex [.vpane.files sash coord 0] 1] + } if {[catch {set rc_geometry $repo_config(gui.geometry)}]} { set rc_geometry {} } @@ -2051,6 +2222,11 @@ proc do_quit {{rc {1}}} { } set ret_code $rc + + # Briefly enable send again, working around Tk bug + # http://sourceforge.net/tracker/?func=detail&atid=112997&aid=1821174&group_id=12997 + tk appname [appname] + destroy . } @@ -2325,8 +2501,6 @@ proc show_less_context {} { ## ## ui construction -load_config 0 -apply_config set ui_comm {} # -- Menu Bar @@ -2358,10 +2532,12 @@ if {[is_enabled multicommit] || [is_enabled singlecommit]} { # menu .mbar.repository -.mbar.repository add command \ - -label [mc "Explore Working Copy"] \ - -command {do_explore} -.mbar.repository add separator +if {![is_bare]} { + .mbar.repository add command \ + -label [mc "Explore Working Copy"] \ + -command {do_explore} + .mbar.repository add separator +} .mbar.repository add command \ -label [mc "Browse Current Branch's Files"] \ @@ -2537,12 +2713,14 @@ if {[is_enabled multicommit] || [is_enabled singlecommit]} { [list .mbar.commit entryconf [.mbar.commit index last] -state] .mbar.commit add command -label [mc "Unstage From Commit"] \ - -command do_unstage_selection + -command do_unstage_selection \ + -accelerator $M1T-U lappend disable_on_lock \ [list .mbar.commit entryconf [.mbar.commit index last] -state] .mbar.commit add command -label [mc "Revert Changes"] \ - -command do_revert_selection + -command do_revert_selection \ + -accelerator $M1T-J lappend disable_on_lock \ [list .mbar.commit entryconf [.mbar.commit index last] -state] @@ -2680,7 +2858,13 @@ bind all <$M1B-Key-W> {destroy [winfo toplevel %W]} set subcommand_args {} proc usage {} { - puts stderr "usage: $::argv0 $::subcommand $::subcommand_args" + set s "usage: $::argv0 $::subcommand $::subcommand_args" + if {[tk windowingsystem] eq "win32"} { + wm withdraw . + tk_messageBox -icon info -title "Usage" -message $s + } else { + puts stderr $s + } exit 1 } @@ -2757,6 +2941,7 @@ blame { set current_branch $head } + wm deiconify . switch -- $subcommand { browser { if {$jump_spec ne {}} usage @@ -2772,7 +2957,12 @@ blame { } blame { if {$head eq {} && ![file exists $path]} { - puts stderr [mc "fatal: cannot stat path %s: No such file or directory" $path] + catch {wm withdraw .} + tk_messageBox \ + -icon error \ + -type ok \ + -title [mc "git-gui: fatal error"] \ + -message [mc "fatal: cannot stat path %s: No such file or directory" $path] exit 1 } blame::new $head $path $jump_spec @@ -2801,14 +2991,13 @@ default { # -- Branch Control # -frame .branch \ - -borderwidth 1 \ - -relief sunken -label .branch.l1 \ +${NS}::frame .branch +if {!$use_ttk} {.branch configure -borderwidth 1 -relief sunken} +${NS}::label .branch.l1 \ -text [mc "Current Branch:"] \ -anchor w \ -justify left -label .branch.cb \ +${NS}::label .branch.cb \ -textvariable current_branch \ -anchor w \ -justify left @@ -2818,15 +3007,20 @@ pack .branch -side top -fill x # -- Main Window Layout # -panedwindow .vpane -orient horizontal -panedwindow .vpane.files -orient vertical -.vpane add .vpane.files -sticky nsew -height 100 -width 200 +${NS}::panedwindow .vpane -orient horizontal +${NS}::panedwindow .vpane.files -orient vertical +if {$use_ttk} { + .vpane add .vpane.files +} else { + .vpane add .vpane.files -sticky nsew -height 100 -width 200 +} pack .vpane -anchor n -side top -fill both -expand 1 # -- Index File List # -frame .vpane.files.index -height 100 -width 200 -label .vpane.files.index.title -text [mc "Staged Changes (Will Commit)"] \ +${NS}::frame .vpane.files.index -height 100 -width 200 +tlabel .vpane.files.index.title \ + -text [mc "Staged Changes (Will Commit)"] \ -background lightgreen -foreground black text $ui_index -background white -foreground black \ -borderwidth 0 \ @@ -2836,8 +3030,8 @@ text $ui_index -background white -foreground black \ -xscrollcommand {.vpane.files.index.sx set} \ -yscrollcommand {.vpane.files.index.sy set} \ -state disabled -scrollbar .vpane.files.index.sx -orient h -command [list $ui_index xview] -scrollbar .vpane.files.index.sy -orient v -command [list $ui_index yview] +${NS}::scrollbar .vpane.files.index.sx -orient h -command [list $ui_index xview] +${NS}::scrollbar .vpane.files.index.sy -orient v -command [list $ui_index yview] pack .vpane.files.index.title -side top -fill x pack .vpane.files.index.sx -side bottom -fill x pack .vpane.files.index.sy -side right -fill y @@ -2845,8 +3039,8 @@ pack $ui_index -side left -fill both -expand 1 # -- Working Directory File List # -frame .vpane.files.workdir -height 100 -width 200 -label .vpane.files.workdir.title -text [mc "Unstaged Changes"] \ +${NS}::frame .vpane.files.workdir -height 100 -width 200 +tlabel .vpane.files.workdir.title -text [mc "Unstaged Changes"] \ -background lightsalmon -foreground black text $ui_workdir -background white -foreground black \ -borderwidth 0 \ @@ -2856,15 +3050,19 @@ text $ui_workdir -background white -foreground black \ -xscrollcommand {.vpane.files.workdir.sx set} \ -yscrollcommand {.vpane.files.workdir.sy set} \ -state disabled -scrollbar .vpane.files.workdir.sx -orient h -command [list $ui_workdir xview] -scrollbar .vpane.files.workdir.sy -orient v -command [list $ui_workdir yview] +${NS}::scrollbar .vpane.files.workdir.sx -orient h -command [list $ui_workdir xview] +${NS}::scrollbar .vpane.files.workdir.sy -orient v -command [list $ui_workdir yview] pack .vpane.files.workdir.title -side top -fill x pack .vpane.files.workdir.sx -side bottom -fill x pack .vpane.files.workdir.sy -side right -fill y pack $ui_workdir -side left -fill both -expand 1 -.vpane.files add .vpane.files.workdir -sticky nsew -.vpane.files add .vpane.files.index -sticky nsew +.vpane.files add .vpane.files.workdir +.vpane.files add .vpane.files.index +if {!$use_ttk} { + .vpane.files paneconfigure .vpane.files.workdir -sticky news + .vpane.files paneconfigure .vpane.files.index -sticky news +} foreach i [list $ui_index $ui_workdir] { rmsel_tag $i @@ -2874,68 +3072,69 @@ unset i # -- Diff and Commit Area # -frame .vpane.lower -height 300 -width 400 -frame .vpane.lower.commarea -frame .vpane.lower.diff -relief sunken -borderwidth 1 +${NS}::frame .vpane.lower -height 300 -width 400 +${NS}::frame .vpane.lower.commarea +${NS}::frame .vpane.lower.diff -relief sunken -borderwidth 1 pack .vpane.lower.diff -fill both -expand 1 pack .vpane.lower.commarea -side bottom -fill x -.vpane add .vpane.lower -sticky nsew +.vpane add .vpane.lower +if {!$use_ttk} {.vpane paneconfigure .vpane.lower -sticky nsew} # -- Commit Area Buttons # -frame .vpane.lower.commarea.buttons -label .vpane.lower.commarea.buttons.l -text {} \ +${NS}::frame .vpane.lower.commarea.buttons +${NS}::label .vpane.lower.commarea.buttons.l -text {} \ -anchor w \ -justify left pack .vpane.lower.commarea.buttons.l -side top -fill x pack .vpane.lower.commarea.buttons -side left -fill y -button .vpane.lower.commarea.buttons.rescan -text [mc Rescan] \ +${NS}::button .vpane.lower.commarea.buttons.rescan -text [mc Rescan] \ -command ui_do_rescan pack .vpane.lower.commarea.buttons.rescan -side top -fill x lappend disable_on_lock \ {.vpane.lower.commarea.buttons.rescan conf -state} -button .vpane.lower.commarea.buttons.incall -text [mc "Stage Changed"] \ +${NS}::button .vpane.lower.commarea.buttons.incall -text [mc "Stage Changed"] \ -command do_add_all pack .vpane.lower.commarea.buttons.incall -side top -fill x lappend disable_on_lock \ {.vpane.lower.commarea.buttons.incall conf -state} if {![is_enabled nocommitmsg]} { - button .vpane.lower.commarea.buttons.signoff -text [mc "Sign Off"] \ + ${NS}::button .vpane.lower.commarea.buttons.signoff -text [mc "Sign Off"] \ -command do_signoff pack .vpane.lower.commarea.buttons.signoff -side top -fill x } -button .vpane.lower.commarea.buttons.commit -text [commit_btn_caption] \ +${NS}::button .vpane.lower.commarea.buttons.commit -text [commit_btn_caption] \ -command do_commit pack .vpane.lower.commarea.buttons.commit -side top -fill x lappend disable_on_lock \ {.vpane.lower.commarea.buttons.commit conf -state} if {![is_enabled nocommit]} { - button .vpane.lower.commarea.buttons.push -text [mc Push] \ + ${NS}::button .vpane.lower.commarea.buttons.push -text [mc Push] \ -command do_push_anywhere pack .vpane.lower.commarea.buttons.push -side top -fill x } # -- Commit Message Buffer # -frame .vpane.lower.commarea.buffer -frame .vpane.lower.commarea.buffer.header +${NS}::frame .vpane.lower.commarea.buffer +${NS}::frame .vpane.lower.commarea.buffer.header set ui_comm .vpane.lower.commarea.buffer.t set ui_coml .vpane.lower.commarea.buffer.header.l if {![is_enabled nocommit]} { - radiobutton .vpane.lower.commarea.buffer.header.new \ + ${NS}::radiobutton .vpane.lower.commarea.buffer.header.new \ -text [mc "New Commit"] \ -command do_select_commit_type \ -variable selected_commit_type \ -value new lappend disable_on_lock \ [list .vpane.lower.commarea.buffer.header.new conf -state] - radiobutton .vpane.lower.commarea.buffer.header.amend \ + ${NS}::radiobutton .vpane.lower.commarea.buffer.header.amend \ -text [mc "Amend Last Commit"] \ -command do_select_commit_type \ -variable selected_commit_type \ @@ -2944,7 +3143,7 @@ if {![is_enabled nocommit]} { [list .vpane.lower.commarea.buffer.header.amend conf -state] } -label $ui_coml \ +${NS}::label $ui_coml \ -anchor w \ -justify left proc trace_commit_type {varname args} { @@ -2976,7 +3175,7 @@ text $ui_comm -background white -foreground black \ -width $repo_config(gui.commitmsgwidth) -height 9 -wrap none \ -font font_diff \ -yscrollcommand {.vpane.lower.commarea.buffer.sby set} -scrollbar .vpane.lower.commarea.buffer.sby \ +${NS}::scrollbar .vpane.lower.commarea.buffer.sby \ -command [list $ui_comm yview] pack .vpane.lower.commarea.buffer.header -side top -fill x pack .vpane.lower.commarea.buffer.sby -side right -fill y @@ -3042,19 +3241,19 @@ proc trace_current_diff_path {varname args} { } trace add variable current_diff_path write trace_current_diff_path -frame .vpane.lower.diff.header -background gold -label .vpane.lower.diff.header.status \ +gold_frame .vpane.lower.diff.header +tlabel .vpane.lower.diff.header.status \ -background gold \ -foreground black \ -width $max_status_desc \ -anchor w \ -justify left -label .vpane.lower.diff.header.file \ +tlabel .vpane.lower.diff.header.file \ -background gold \ -foreground black \ -anchor w \ -justify left -label .vpane.lower.diff.header.path \ +tlabel .vpane.lower.diff.header.path \ -background gold \ -foreground black \ -anchor w \ @@ -3078,18 +3277,18 @@ bind_button3 .vpane.lower.diff.header.path "tk_popup $ctxm %X %Y" # -- Diff Body # -frame .vpane.lower.diff.body +${NS}::frame .vpane.lower.diff.body set ui_diff .vpane.lower.diff.body.t text $ui_diff -background white -foreground black \ -borderwidth 0 \ - -width 80 -height 15 -wrap none \ + -width 80 -height 5 -wrap none \ -font font_diff \ -xscrollcommand {.vpane.lower.diff.body.sbx set} \ -yscrollcommand {.vpane.lower.diff.body.sby set} \ -state disabled -scrollbar .vpane.lower.diff.body.sbx -orient horizontal \ +${NS}::scrollbar .vpane.lower.diff.body.sbx -orient horizontal \ -command [list $ui_diff xview] -scrollbar .vpane.lower.diff.body.sby -orient vertical \ +${NS}::scrollbar .vpane.lower.diff.body.sby -orient vertical \ -command [list $ui_diff yview] pack .vpane.lower.diff.body.sbx -side bottom -fill x pack .vpane.lower.diff.body.sby -side right -fill y @@ -3133,15 +3332,6 @@ $ui_diff tag raise sel # proc create_common_diff_popup {ctxm} { - $ctxm add command \ - -label [mc "Show Less Context"] \ - -command show_less_context - lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] - $ctxm add command \ - -label [mc "Show More Context"] \ - -command show_more_context - lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] - $ctxm add separator $ctxm add command \ -label [mc Refresh] \ -command reshow_diff @@ -3193,10 +3383,19 @@ set ui_diff_applyhunk [$ctxm index last] lappend diff_actions [list $ctxm entryconf $ui_diff_applyhunk -state] $ctxm add command \ -label [mc "Apply/Reverse Line"] \ - -command {apply_line $cursorX $cursorY; do_rescan} + -command {apply_range_or_line $cursorX $cursorY; do_rescan} set ui_diff_applyline [$ctxm index last] lappend diff_actions [list $ctxm entryconf $ui_diff_applyline -state] $ctxm add separator +$ctxm add command \ + -label [mc "Show Less Context"] \ + -command show_less_context +lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] +$ctxm add command \ + -label [mc "Show More Context"] \ + -command show_more_context +lappend diff_actions [list $ctxm entryconf [$ctxm index last] -state] +$ctxm add separator create_common_diff_popup $ctxm set ctxmmg .vpane.lower.diff.body.ctxmmg @@ -3219,9 +3418,53 @@ $ctxmmg add command \ -command {merge_resolve_one 1} lappend diff_actions [list $ctxmmg entryconf [$ctxmmg index last] -state] $ctxmmg add separator +$ctxmmg add command \ + -label [mc "Show Less Context"] \ + -command show_less_context +lappend diff_actions [list $ctxmmg entryconf [$ctxmmg index last] -state] +$ctxmmg add command \ + -label [mc "Show More Context"] \ + -command show_more_context +lappend diff_actions [list $ctxmmg entryconf [$ctxmmg index last] -state] +$ctxmmg add separator create_common_diff_popup $ctxmmg -proc popup_diff_menu {ctxm ctxmmg x y X Y} { +set ctxmsm .vpane.lower.diff.body.ctxmsm +menu $ctxmsm -tearoff 0 +$ctxmsm add command \ + -label [mc "Visualize These Changes In The Submodule"] \ + -command {do_gitk -- true} +lappend diff_actions [list $ctxmsm entryconf [$ctxmsm index last] -state] +$ctxmsm add command \ + -label [mc "Visualize Current Branch History In The Submodule"] \ + -command {do_gitk {} true} +lappend diff_actions [list $ctxmsm entryconf [$ctxmsm index last] -state] +$ctxmsm add command \ + -label [mc "Visualize All Branch History In The Submodule"] \ + -command {do_gitk --all true} +lappend diff_actions [list $ctxmsm entryconf [$ctxmsm index last] -state] +$ctxmsm add separator +$ctxmsm add command \ + -label [mc "Start git gui In The Submodule"] \ + -command {do_git_gui} +lappend diff_actions [list $ctxmsm entryconf [$ctxmsm index last] -state] +$ctxmsm add separator +create_common_diff_popup $ctxmsm + +proc has_textconv {path} { + if {[is_config_false gui.textconv]} { + return 0 + } + set filter [gitattr $path diff set] + set textconv [get_config [join [list diff $filter textconv] .]] + if {$filter ne {set} && $textconv ne {}} { + return 1 + } else { + return 0 + } +} + +proc popup_diff_menu {ctxm ctxmmg ctxmsm x y X Y} { global current_diff_path file_states set ::cursorX $x set ::cursorY $y @@ -3232,20 +3475,32 @@ proc popup_diff_menu {ctxm ctxmmg x y X Y} { } if {[string first {U} $state] >= 0} { tk_popup $ctxmmg $X $Y + } elseif {$::is_submodule_diff} { + tk_popup $ctxmsm $X $Y } else { + set has_range [expr {[$::ui_diff tag nextrange sel 0.0] != {}}] if {$::ui_index eq $::current_diff_side} { set l [mc "Unstage Hunk From Commit"] - set t [mc "Unstage Line From Commit"] + if {$has_range} { + set t [mc "Unstage Lines From Commit"] + } else { + set t [mc "Unstage Line From Commit"] + } } else { set l [mc "Stage Hunk For Commit"] - set t [mc "Stage Line For Commit"] + if {$has_range} { + set t [mc "Stage Lines For Commit"] + } else { + set t [mc "Stage Line For Commit"] + } } - if {$::is_3way_diff || $::is_submodule_diff + if {$::is_3way_diff || $current_diff_path eq {} || {__} eq $state || {_O} eq $state || {_T} eq $state - || {T_} eq $state} { + || {T_} eq $state + || [has_textconv $current_diff_path]} { set s disabled } else { set s normal @@ -3255,7 +3510,7 @@ proc popup_diff_menu {ctxm ctxmmg x y X Y} { tk_popup $ctxm $X $Y } } -bind_button3 $ui_diff [list popup_diff_menu $ctxm $ctxmmg %x %y %X %Y] +bind_button3 $ui_diff [list popup_diff_menu $ctxm $ctxmmg $ctxmsm %x %y %X %Y] # -- Status Bar # @@ -3265,24 +3520,44 @@ $main_status show [mc "Initializing..."] # -- Load geometry # -catch { -set gm $repo_config(gui.geometry) -wm geometry . [lindex $gm 0] -.vpane sash place 0 \ - [lindex $gm 1] \ - [lindex [.vpane sash coord 0] 1] -.vpane.files sash place 0 \ - [lindex [.vpane.files sash coord 0] 0] \ - [lindex $gm 2] -unset gm +proc on_ttk_pane_mapped {w pane pos} { + bind $w {} + after 0 [list after idle [list $w sashpos $pane $pos]] +} +proc on_tk_pane_mapped {w pane x y} { + bind $w {} + after 0 [list after idle [list $w sash place $pane $x $y]] +} +proc on_application_mapped {} { + global repo_config use_ttk + bind . {} + set gm $repo_config(gui.geometry) + if {$use_ttk} { + bind .vpane \ + [list on_ttk_pane_mapped %W 0 [lindex $gm 1]] + bind .vpane.files \ + [list on_ttk_pane_mapped %W 0 [lindex $gm 2]] + } else { + bind .vpane \ + [list on_tk_pane_mapped %W 0 \ + [lindex $gm 1] \ + [lindex [.vpane sash coord 0] 1]] + bind .vpane.files \ + [list on_tk_pane_mapped %W 0 \ + [lindex [.vpane.files sash coord 0] 0] \ + [lindex $gm 2]] + } + wm geometry . [lindex $gm 0] +} +if {[info exists repo_config(gui.geometry)]} { + bind . [list on_application_mapped] + wm geometry . [lindex $repo_config(gui.geometry) 0] } # -- Load window state # -catch { -set gws $repo_config(gui.wmstate) -wm state . $gws -unset gws +if {[info exists repo_config(gui.wmstate)]} { + catch {wm state . $repo_config(gui.wmstate)} } # -- Key Bindings @@ -3290,6 +3565,10 @@ unset gws bind $ui_comm <$M1B-Key-Return> {do_commit;break} bind $ui_comm <$M1B-Key-t> {do_add_selection;break} bind $ui_comm <$M1B-Key-T> {do_add_selection;break} +bind $ui_comm <$M1B-Key-u> {do_unstage_selection;break} +bind $ui_comm <$M1B-Key-U> {do_unstage_selection;break} +bind $ui_comm <$M1B-Key-j> {do_revert_selection;break} +bind $ui_comm <$M1B-Key-J> {do_revert_selection;break} bind $ui_comm <$M1B-Key-i> {do_add_all;break} bind $ui_comm <$M1B-Key-I> {do_add_all;break} bind $ui_comm <$M1B-Key-x> {tk_textCut %W;break} @@ -3346,6 +3625,8 @@ bind . <$M1B-Key-s> do_signoff bind . <$M1B-Key-S> do_signoff bind . <$M1B-Key-t> do_add_selection bind . <$M1B-Key-T> do_add_selection +bind . <$M1B-Key-j> do_revert_selection +bind . <$M1B-Key-J> do_revert_selection bind . <$M1B-Key-i> do_add_all bind . <$M1B-Key-I> do_add_all bind . <$M1B-Key-minus> {show_less_context;break} @@ -3364,7 +3645,7 @@ unset i set file_lists($ui_index) [list] set file_lists($ui_workdir) [list] -wm title . "[appname] ([reponame]) [file normalize [file dirname [gitdir]]]" +wm title . "[appname] ([reponame]) [file normalize $_gitworktree]" focus -force $ui_comm # -- Warn the user about environmental problems. Cygwin's Tcl @@ -3537,3 +3818,9 @@ if {[is_enabled retcode]} { if {$picked && [is_config_true gui.autoexplore]} { do_explore } + +# Local variables: +# mode: tcl +# indent-tabs-mode: t +# tab-width: 4 +# End: