@@ -55,7 +55,7 @@ proc reshow_diff {{after {}}} {
55
55
56
56
proc force_diff_encoding {enc} {
57
57
global current_diff_path
58
-
58
+
59
59
if {$current_diff_path ne {}} {
60
60
force_path_encoding $current_diff_path $enc
61
61
reshow_diff
@@ -567,24 +567,31 @@ proc read_diff {fd conflict_size cont_info} {
567
567
}
568
568
}
569
569
570
- proc apply_hunk {x y} {
570
+ proc apply_or_revert_hunk {x y revert } {
571
571
global current_diff_path current_diff_header current_diff_side
572
- global ui_diff ui_index file_states
572
+ global ui_diff ui_index file_states last_revert last_revert_enc
573
573
574
574
if {$current_diff_path eq {} || $current_diff_header eq {}} return
575
575
if {![lock_index apply_hunk]} return
576
576
577
- set apply_cmd {apply --cached -- whitespace=nowarn}
577
+ set apply_cmd {apply --whitespace=nowarn}
578
578
set mi [lindex $file_states($current_diff_path) 0]
579
579
if {$current_diff_side eq $ui_index } {
580
580
set failed_msg [mc " Failed to unstage selected hunk." ]
581
- lappend apply_cmd --reverse
581
+ lappend apply_cmd --reverse --cached
582
582
if {[string index $mi 0] ne {M}} {
583
583
unlock_index
584
584
return
585
585
}
586
586
} else {
587
- set failed_msg [mc " Failed to stage selected hunk." ]
587
+ if {$revert } {
588
+ set failed_msg [mc " Failed to revert selected hunk." ]
589
+ lappend apply_cmd --reverse
590
+ } else {
591
+ set failed_msg [mc " Failed to stage selected hunk." ]
592
+ lappend apply_cmd --cached
593
+ }
594
+
588
595
if {[string index $mi 1] ne {M}} {
589
596
unlock_index
590
597
return
@@ -603,29 +610,40 @@ proc apply_hunk {x y} {
603
610
set e_lno end
604
611
}
605
612
613
+ set wholepatch " $current_diff_header [ $ui_diff get $s_lno $e_lno ] "
614
+
606
615
if {[catch {
607
616
set enc [get_path_encoding $current_diff_path ]
608
617
set p [eval git_write $apply_cmd ]
609
618
fconfigure $p -translation binary -encoding $enc
610
- puts -nonewline $p $current_diff_header
611
- puts -nonewline $p [$ui_diff get $s_lno $e_lno ]
619
+ puts -nonewline $p $wholepatch
612
620
close $p } err]} {
613
621
error_popup " $failed_msg \n\n $err "
614
622
unlock_index
615
623
return
616
624
}
617
625
626
+ if {$revert } {
627
+ # Save a copy of this patch for undoing reverts.
628
+ set last_revert $wholepatch
629
+ set last_revert_enc $enc
630
+ }
631
+
618
632
$ui_diff conf -state normal
619
633
$ui_diff delete $s_lno $e_lno
620
634
$ui_diff conf -state disabled
621
635
636
+ # Check if the hunk was the last one in the file.
622
637
if {[$ui_diff get 1.0 end] eq " \n " } {
623
638
set o _
624
639
} else {
625
640
set o ?
626
641
}
627
642
628
- if {$current_diff_side eq $ui_index } {
643
+ # Update the status flags.
644
+ if {$revert } {
645
+ set mi [string index $mi 0]$o
646
+ } elseif {$current_diff_side eq $ui_index } {
629
647
set mi ${o} M
630
648
} elseif {[string index $mi 0] eq {_}} {
631
649
set mi M$o
@@ -640,9 +658,9 @@ proc apply_hunk {x y} {
640
658
}
641
659
}
642
660
643
- proc apply_range_or_line {x y} {
661
+ proc apply_or_revert_range_or_line {x y revert } {
644
662
global current_diff_path current_diff_header current_diff_side
645
- global ui_diff ui_index file_states
663
+ global ui_diff ui_index file_states last_revert
646
664
647
665
set selected [$ui_diff tag nextrange sel 0.0]
648
666
@@ -660,19 +678,27 @@ proc apply_range_or_line {x y} {
660
678
if {$current_diff_path eq {} || $current_diff_header eq {}} return
661
679
if {![lock_index apply_hunk]} return
662
680
663
- set apply_cmd {apply --cached -- whitespace=nowarn}
681
+ set apply_cmd {apply --whitespace=nowarn}
664
682
set mi [lindex $file_states($current_diff_path) 0]
665
683
if {$current_diff_side eq $ui_index } {
666
684
set failed_msg [mc " Failed to unstage selected line." ]
667
685
set to_context {+}
668
- lappend apply_cmd --reverse
686
+ lappend apply_cmd --reverse --cached
669
687
if {[string index $mi 0] ne {M}} {
670
688
unlock_index
671
689
return
672
690
}
673
691
} else {
674
- set failed_msg [mc " Failed to stage selected line." ]
675
- set to_context {-}
692
+ if {$revert } {
693
+ set failed_msg [mc " Failed to revert selected line." ]
694
+ set to_context {+}
695
+ lappend apply_cmd --reverse
696
+ } else {
697
+ set failed_msg [mc " Failed to stage selected line." ]
698
+ set to_context {-}
699
+ lappend apply_cmd --cached
700
+ }
701
+
676
702
if {[string index $mi 1] ne {M}} {
677
703
unlock_index
678
704
return
@@ -829,7 +855,47 @@ proc apply_range_or_line {x y} {
829
855
puts -nonewline $p $wholepatch
830
856
close $p } err]} {
831
857
error_popup " $failed_msg \n\n $err "
858
+ unlock_index
859
+ return
860
+ }
861
+
862
+ if {$revert } {
863
+ # Save a copy of this patch for undoing reverts.
864
+ set last_revert $current_diff_header$wholepatch
865
+ set last_revert_enc $enc
832
866
}
833
867
834
868
unlock_index
835
869
}
870
+
871
+ # Undo the last line/hunk reverted. When hunks and lines are reverted, a copy
872
+ # of the diff applied is saved. Re-apply that diff to undo the revert.
873
+ #
874
+ # Right now, we only use a single variable to hold the copy, and not a
875
+ # stack/deque for simplicity, so multiple undos are not possible. Maybe this
876
+ # can be added if the need for something like this is felt in the future.
877
+ proc undo_last_revert {} {
878
+ global last_revert current_diff_path current_diff_header
879
+ global last_revert_enc
880
+
881
+ if {$last_revert eq {}} return
882
+ if {![lock_index apply_hunk]} return
883
+
884
+ set apply_cmd {apply --whitespace=nowarn}
885
+ set failed_msg [mc " Failed to undo last revert." ]
886
+
887
+ if {[catch {
888
+ set enc $last_revert_enc
889
+ set p [eval git_write $apply_cmd ]
890
+ fconfigure $p -translation binary -encoding $enc
891
+ puts -nonewline $p $last_revert
892
+ close $p } err]} {
893
+ error_popup " $failed_msg \n\n $err "
894
+ unlock_index
895
+ return
896
+ }
897
+
898
+ set last_revert {}
899
+
900
+ unlock_index
901
+ }
0 commit comments