Merge branch 'mh/release-commit-memory-fix'
[gitweb.git] / git-gui / git-gui.sh
index 6ec562d5da3cf07afb27f88b10763f1104134baf..fd476b69993c68ddd58e274ae97e0f91c0086951 100755 (executable)
@@ -1340,6 +1340,7 @@ set HEAD {}
 set PARENT {}
 set MERGE_HEAD [list]
 set commit_type {}
+set commit_type_is_amend 0
 set empty_tree {}
 set current_branch {}
 set is_detached 0
@@ -1347,8 +1348,9 @@ 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
+set last_revert {}
+set last_revert_enc {}
 
 set nullid "0000000000000000000000000000000000000000"
 set nullid2 "0000000000000000000000000000000000000001"
@@ -1434,7 +1436,7 @@ proc PARENT {} {
 }
 
 proc force_amend {} {
-       global selected_commit_type
+       global commit_type_is_amend
        global HEAD PARENT MERGE_HEAD commit_type
 
        repository_state newType newHEAD newMERGE_HEAD
@@ -1443,7 +1445,7 @@ proc force_amend {} {
        set MERGE_HEAD $newMERGE_HEAD
        set commit_type $newType
 
-       set selected_commit_type amend
+       set commit_type_is_amend 1
        do_select_commit_type
 }
 
@@ -2494,7 +2496,7 @@ proc force_first_diff {after} {
 
 proc toggle_or_diff {mode w args} {
        global file_states file_lists current_diff_path ui_index ui_workdir
-       global last_clicked selected_paths
+       global last_clicked selected_paths file_lists_last_clicked
 
        if {$mode eq "click"} {
                foreach {x y} $args break
@@ -2551,6 +2553,8 @@ proc toggle_or_diff {mode w args} {
        $ui_index tag remove in_sel 0.0 end
        $ui_workdir tag remove in_sel 0.0 end
 
+       set file_lists_last_clicked($w) $path
+
        # Determine the state of the file
        if {[info exists file_states($path)]} {
                set state [lindex $file_states($path) 0]
@@ -2664,6 +2668,32 @@ proc show_less_context {} {
        }
 }
 
+proc focus_widget {widget} {
+       global file_lists last_clicked selected_paths
+       global file_lists_last_clicked
+
+       if {[llength $file_lists($widget)] > 0} {
+               set path $file_lists_last_clicked($widget)
+               set index [lsearch -sorted -exact $file_lists($widget) $path]
+               if {$index < 0} {
+                       set index 0
+                       set path [lindex $file_lists($widget) $index]
+               }
+
+               focus $widget
+               set last_clicked [list $widget [expr $index + 1]]
+               array unset selected_paths
+               set selected_paths($path) 1
+               show_diff $path $widget
+       }
+}
+
+proc toggle_commit_type {} {
+       global commit_type_is_amend
+       set commit_type_is_amend [expr !$commit_type_is_amend]
+       do_select_commit_type
+}
+
 ######################################################################
 ##
 ## ui construction
@@ -2852,19 +2882,11 @@ if {[is_enabled multicommit] || [is_enabled singlecommit]} {
        menu .mbar.commit
 
        if {![is_enabled nocommit]} {
-               .mbar.commit add radiobutton \
-                       -label [mc "New Commit"] \
-                       -command do_select_commit_type \
-                       -variable selected_commit_type \
-                       -value new
-               lappend disable_on_lock \
-                       [list .mbar.commit entryconf [.mbar.commit index last] -state]
-
-               .mbar.commit add radiobutton \
+               .mbar.commit add checkbutton \
                        -label [mc "Amend Last Commit"] \
-                       -command do_select_commit_type \
-                       -variable selected_commit_type \
-                       -value amend
+                       -accelerator $M1T-E \
+                       -variable commit_type_is_amend \
+                       -command do_select_commit_type
                lappend disable_on_lock \
                        [list .mbar.commit entryconf [.mbar.commit index last] -state]
 
@@ -3352,18 +3374,10 @@ set ui_comm .vpane.lower.commarea.buffer.frame.t
 set ui_coml .vpane.lower.commarea.buffer.header.l
 
 if {![is_enabled nocommit]} {
-       ${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]
-       ${NS}::radiobutton .vpane.lower.commarea.buffer.header.amend \
+       ${NS}::checkbutton .vpane.lower.commarea.buffer.header.amend \
                -text [mc "Amend Last Commit"] \
-               -command do_select_commit_type \
-               -variable selected_commit_type \
-               -value amend
+               -variable commit_type_is_amend \
+               -command do_select_commit_type
        lappend disable_on_lock \
                [list .vpane.lower.commarea.buffer.header.amend conf -state]
 }
@@ -3388,7 +3402,6 @@ pack $ui_coml -side left -fill x
 
 if {![is_enabled nocommit]} {
        pack .vpane.lower.commarea.buffer.header.amend -side right
-       pack .vpane.lower.commarea.buffer.header.new -side right
 }
 
 textframe .vpane.lower.commarea.buffer.frame
@@ -3402,10 +3415,16 @@ ttext $ui_comm -background white -foreground black \
        -relief sunken \
        -width $repo_config(gui.commitmsgwidth) -height 9 -wrap none \
        -font font_diff \
+       -xscrollcommand {.vpane.lower.commarea.buffer.frame.sbx set} \
        -yscrollcommand {.vpane.lower.commarea.buffer.frame.sby set}
+${NS}::scrollbar .vpane.lower.commarea.buffer.frame.sbx \
+       -orient horizontal \
+       -command [list $ui_comm xview]
 ${NS}::scrollbar .vpane.lower.commarea.buffer.frame.sby \
+       -orient vertical \
        -command [list $ui_comm yview]
 
+pack .vpane.lower.commarea.buffer.frame.sbx -side bottom -fill x
 pack .vpane.lower.commarea.buffer.frame.sby -side right -fill y
 pack $ui_comm -side left -fill y
 pack .vpane.lower.commarea.buffer.header -side top -fill x
@@ -3621,15 +3640,31 @@ set ctxm .vpane.lower.diff.body.ctxm
 menu $ctxm -tearoff 0
 $ctxm add command \
        -label [mc "Apply/Reverse Hunk"] \
-       -command {apply_hunk $cursorX $cursorY}
+       -command {apply_or_revert_hunk $cursorX $cursorY 0}
 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_range_or_line $cursorX $cursorY; do_rescan}
+       -command {apply_or_revert_range_or_line $cursorX $cursorY 0; 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 "Revert Hunk"] \
+       -command {apply_or_revert_hunk $cursorX $cursorY 1}
+set ui_diff_reverthunk [$ctxm index last]
+lappend diff_actions [list $ctxm entryconf $ui_diff_reverthunk -state]
+$ctxm add command \
+       -label [mc "Revert Line"] \
+       -command {apply_or_revert_range_or_line $cursorX $cursorY 1; do_rescan}
+set ui_diff_revertline [$ctxm index last]
+lappend diff_actions [list $ctxm entryconf $ui_diff_revertline -state]
+$ctxm add command \
+       -label [mc "Undo Last Revert"] \
+       -command {undo_last_revert; do_rescan}
+set ui_diff_undorevert [$ctxm index last]
+lappend diff_actions [list $ctxm entryconf $ui_diff_undorevert -state]
+$ctxm add separator
 $ctxm add command \
        -label [mc "Show Less Context"] \
        -command show_less_context
@@ -3708,7 +3743,7 @@ proc has_textconv {path} {
 }
 
 proc popup_diff_menu {ctxm ctxmmg ctxmsm x y X Y} {
-       global current_diff_path file_states
+       global current_diff_path file_states last_revert
        set ::cursorX $x
        set ::cursorY $y
        if {[info exists file_states($current_diff_path)]} {
@@ -3722,19 +3757,28 @@ proc popup_diff_menu {ctxm ctxmmg ctxmsm x y X Y} {
                tk_popup $ctxmsm $X $Y
        } else {
                set has_range [expr {[$::ui_diff tag nextrange sel 0.0] != {}}]
+               set u [mc "Undo Last Revert"]
                if {$::ui_index eq $::current_diff_side} {
                        set l [mc "Unstage Hunk From Commit"]
+                       set h [mc "Revert Hunk"]
+
                        if {$has_range} {
                                set t [mc "Unstage Lines From Commit"]
+                               set r [mc "Revert Lines"]
                        } else {
                                set t [mc "Unstage Line From Commit"]
+                               set r [mc "Revert Line"]
                        }
                } else {
                        set l [mc "Stage Hunk For Commit"]
+                       set h [mc "Revert Hunk"]
+
                        if {$has_range} {
                                set t [mc "Stage Lines For Commit"]
+                               set r [mc "Revert Lines"]
                        } else {
                                set t [mc "Stage Line For Commit"]
+                               set r [mc "Revert Line"]
                        }
                }
                if {$::is_3way_diff
@@ -3745,11 +3789,35 @@ proc popup_diff_menu {ctxm ctxmmg ctxmsm x y X Y} {
                        || [string match {T?} $state]
                        || [has_textconv $current_diff_path]} {
                        set s disabled
+                       set revert_state disabled
                } else {
                        set s normal
+
+                       # Only allow reverting changes in the working tree. If
+                       # the user wants to revert changes in the index, they
+                       # need to unstage those first.
+                       if {$::ui_workdir eq $::current_diff_side} {
+                               set revert_state normal
+                       } else {
+                               set revert_state disabled
+                       }
+               }
+
+               if {$last_revert eq {}} {
+                       set undo_state disabled
+               } else {
+                       set undo_state normal
                }
+
                $ctxm entryconf $::ui_diff_applyhunk -state $s -label $l
                $ctxm entryconf $::ui_diff_applyline -state $s -label $t
+               $ctxm entryconf $::ui_diff_revertline -state $revert_state \
+                       -label $r
+               $ctxm entryconf $::ui_diff_reverthunk -state $revert_state \
+                       -label $h
+               $ctxm entryconf $::ui_diff_undorevert -state $undo_state \
+                       -label $u
+
                tk_popup $ctxm $X $Y
        }
 }
@@ -3876,6 +3944,8 @@ 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-e> toggle_commit_type
+bind .   <$M1B-Key-E> toggle_commit_type
 bind .   <$M1B-Key-minus> {show_less_context;break}
 bind .   <$M1B-Key-KP_Subtract> {show_less_context;break}
 bind .   <$M1B-Key-equal> {show_more_context;break}
@@ -3892,6 +3962,14 @@ foreach i [list $ui_index $ui_workdir] {
 }
 unset i
 
+bind .   <Alt-Key-1> {focus_widget $::ui_workdir}
+bind .   <Alt-Key-2> {focus_widget $::ui_index}
+bind .   <Alt-Key-3> {focus $::ui_diff}
+bind .   <Alt-Key-4> {focus $::ui_comm}
+
+set file_lists_last_clicked($ui_index) {}
+set file_lists_last_clicked($ui_workdir) {}
+
 set file_lists($ui_index) [list]
 set file_lists($ui_workdir) [list]