summaryrefslogtreecommitdiff
path: root/git-gui/lib/diff.tcl
diff options
context:
space:
mode:
Diffstat (limited to 'git-gui/lib/diff.tcl')
-rw-r--r--git-gui/lib/diff.tcl87
1 files changed, 87 insertions, 0 deletions
diff --git a/git-gui/lib/diff.tcl b/git-gui/lib/diff.tcl
index d04f6dbde2..96ba94906c 100644
--- a/git-gui/lib/diff.tcl
+++ b/git-gui/lib/diff.tcl
@@ -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
+}