Merge git://repo.or.cz/git-gui

* git://repo.or.cz/git-gui:
  git-gui: Implement "Stage/Unstage Line"
  git-gui: Don't select the wrong file if the last listed file is staged.
  git-gui: Fix accidental staged state toggle when clicking top pixel row
  git-gui: Move on to the next filename after staging/unstaging a change
This commit is contained in:
Junio C Hamano 2008-07-06 12:55:34 -07:00
commit 87fb597d4e
2 changed files with 125 additions and 3 deletions

View File

@ -1774,6 +1774,11 @@ proc do_commit {} {
commit_tree
}
proc next_diff {} {
global next_diff_p next_diff_w next_diff_i
show_diff $next_diff_p $next_diff_w $next_diff_i
}
proc toggle_or_diff {w x y} {
global file_states file_lists current_diff_path ui_index ui_workdir
global last_clicked selected_paths
@ -1792,12 +1797,34 @@ proc toggle_or_diff {w x y} {
$ui_index tag remove in_sel 0.0 end
$ui_workdir tag remove in_sel 0.0 end
if {$col == 0} {
if {$current_diff_path eq $path} {
if {$col == 0 && $y > 1} {
set i [expr {$lno-1}]
set ll [expr {[llength $file_lists($w)]-1}]
if {$i == $ll && $i == 0} {
set after {reshow_diff;}
} else {
set after {}
global next_diff_p next_diff_w next_diff_i
set next_diff_w $w
if {$i < $ll} {
set i [expr {$i + 1}]
set next_diff_i $i
} else {
set next_diff_i $i
set i [expr {$i - 1}]
}
set next_diff_p [lindex $file_lists($w) $i]
if {$next_diff_p ne {} && $current_diff_path ne {}} {
set after {next_diff;}
} else {
set after {}
}
}
if {$w eq $ui_index} {
update_indexinfo \
"Unstaging [short_path $path] from commit" \
@ -2639,6 +2666,11 @@ $ctxm add command \
-command {apply_hunk $cursorX $cursorY}
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}
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"] \
@ -2687,8 +2719,10 @@ proc popup_diff_menu {ctxm x y X Y} {
set ::cursorY $y
if {$::ui_index eq $::current_diff_side} {
set l [mc "Unstage Hunk From Commit"]
set t [mc "Unstage Line From Commit"]
} else {
set l [mc "Stage Hunk For Commit"]
set t [mc "Stage Line For Commit"]
}
if {$::is_3way_diff
|| $current_diff_path eq {}
@ -2699,6 +2733,7 @@ proc popup_diff_menu {ctxm x y X Y} {
set s normal
}
$ctxm entryconf $::ui_diff_applyhunk -state $s -label $l
$ctxm entryconf $::ui_diff_applyline -state $s -label $t
tk_popup $ctxm $X $Y
}
bind_button3 $ui_diff [list popup_diff_menu $ctxm %x %y %X %Y]

View File

@ -362,3 +362,90 @@ proc apply_hunk {x y} {
set current_diff_path $current_diff_path
}
}
proc apply_line {x y} {
global current_diff_path current_diff_header current_diff_side
global ui_diff ui_index file_states
if {$current_diff_path eq {} || $current_diff_header eq {}} return
if {![lock_index apply_hunk]} return
set apply_cmd {apply --cached --whitespace=nowarn}
set mi [lindex $file_states($current_diff_path) 0]
if {$current_diff_side eq $ui_index} {
set failed_msg [mc "Failed to unstage selected line."]
set to_context {+}
lappend apply_cmd --reverse
if {[string index $mi 0] ne {M}} {
unlock_index
return
}
} else {
set failed_msg [mc "Failed to stage selected line."]
set to_context {-}
if {[string index $mi 1] ne {M}} {
unlock_index
return
}
}
set the_l [$ui_diff index @$x,$y]
# operate only on change lines
set c1 [$ui_diff get "$the_l linestart"]
if {$c1 ne {+} && $c1 ne {-}} {
unlock_index
return
}
set sign $c1
set i_l [$ui_diff search -backwards -regexp ^@@ $the_l 0.0]
if {$i_l eq {}} {
unlock_index
return
}
# $i_l is now at the beginning of a line
# pick start line number from hunk header
set hh [$ui_diff get $i_l "$i_l + 1 lines"]
set hh [lindex [split $hh ,] 0]
set hln [lindex [split $hh -] 1]
set n 0
set i_l [$ui_diff index "$i_l + 1 lines"]
set patch {}
while {[$ui_diff compare $i_l < "end - 1 chars"] &&
[$ui_diff get $i_l "$i_l + 2 chars"] ne {@@}} {
set next_l [$ui_diff index "$i_l + 1 lines"]
set c1 [$ui_diff get $i_l]
if {[$ui_diff compare $i_l <= $the_l] &&
[$ui_diff compare $the_l < $next_l]} {
# the line to stage/unstage
set ln [$ui_diff get $i_l $next_l]
set patch "$patch$ln"
} elseif {$c1 ne {-} && $c1 ne {+}} {
# context line
set ln [$ui_diff get $i_l $next_l]
set patch "$patch$ln"
set n [expr $n+1]
} elseif {$c1 eq $to_context} {
# turn change line into context line
set ln [$ui_diff get "$i_l + 1 chars" $next_l]
set patch "$patch $ln"
set n [expr $n+1]
}
set i_l $next_l
}
set patch "@@ -$hln,$n +$hln,[eval expr $n $sign 1] @@\n$patch"
if {[catch {
set p [eval git_write $apply_cmd]
fconfigure $p -translation binary -encoding binary
puts -nonewline $p $current_diff_header
puts -nonewline $p $patch
close $p} err]} {
error_popup [append $failed_msg "\n\n$err"]
}
unlock_index
}