@@ -677,7 +677,7 @@ sub add_untracked_cmd {
677677sub run_git_apply {
678678 my $cmd = shift ;
679679 my $fh ;
680- open $fh , ' | git ' . $cmd . " --recount -- allow-overlap" ;
680+ open $fh , ' | git ' . $cmd . " --allow-overlap" ;
681681 print $fh @_ ;
682682 return close $fh ;
683683}
@@ -751,6 +751,15 @@ sub parse_hunk_header {
751751 return ($o_ofs , $o_cnt , $n_ofs , $n_cnt );
752752}
753753
754+ sub format_hunk_header {
755+ my ($o_ofs , $o_cnt , $n_ofs , $n_cnt ) = @_ ;
756+ return (" @@ -$o_ofs " .
757+ (($o_cnt != 1) ? " ,$o_cnt " : ' ' ) .
758+ " +$n_ofs " .
759+ (($n_cnt != 1) ? " ,$n_cnt " : ' ' ) .
760+ " @@\n " );
761+ }
762+
754763sub split_hunk {
755764 my ($text , $display ) = @_ ;
756765 my @split = ();
@@ -784,6 +793,11 @@ sub split_hunk {
784793 while (++$i < @$text ) {
785794 my $line = $text -> [$i ];
786795 my $display = $display -> [$i ];
796+ if ($line =~ / ^\\ / ) {
797+ push @{$this -> {TEXT }}, $line ;
798+ push @{$this -> {DISPLAY }}, $display ;
799+ next ;
800+ }
787801 if ($line =~ / ^ / ) {
788802 if ($this -> {ADDDEL } &&
789803 !defined $next_hunk_start ) {
@@ -838,11 +852,7 @@ sub split_hunk {
838852 my $o_cnt = $hunk -> {OCNT };
839853 my $n_cnt = $hunk -> {NCNT };
840854
841- my $head = (" @@ -$o_ofs " .
842- (($o_cnt != 1) ? " ,$o_cnt " : ' ' ) .
843- " +$n_ofs " .
844- (($n_cnt != 1) ? " ,$n_cnt " : ' ' ) .
845- " @@\n " );
855+ my $head = format_hunk_header($o_ofs , $o_cnt , $n_ofs , $n_cnt );
846856 my $display_head = $head ;
847857 unshift @{$hunk -> {TEXT }}, $head ;
848858 if ($diff_use_color ) {
@@ -886,6 +896,9 @@ sub merge_hunk {
886896 $n_cnt ++;
887897 push @line , $line ;
888898 next ;
899+ } elsif ($line =~ / ^\\ / ) {
900+ push @line , $line ;
901+ next ;
889902 }
890903
891904 last if ($o1_ofs <= $ofs );
@@ -904,6 +917,9 @@ sub merge_hunk {
904917 $n_cnt ++;
905918 push @line , $line ;
906919 next ;
920+ } elsif ($line =~ / ^\\ / ) {
921+ push @line , $line ;
922+ next ;
907923 }
908924 $ofs ++;
909925 $o_cnt ++;
@@ -912,11 +928,7 @@ sub merge_hunk {
912928 }
913929 push @line , $line ;
914930 }
915- my $head = (" @@ -$o0_ofs " .
916- (($o_cnt != 1) ? " ,$o_cnt " : ' ' ) .
917- " +$n0_ofs " .
918- (($n_cnt != 1) ? " ,$n_cnt " : ' ' ) .
919- " @@\n " );
931+ my $head = format_hunk_header($o0_ofs , $o_cnt , $n0_ofs , $n_cnt );
920932 @{$prev -> {TEXT }} = ($head , @line );
921933}
922934
@@ -925,14 +937,35 @@ sub coalesce_overlapping_hunks {
925937 my @out = ();
926938
927939 my ($last_o_ctx , $last_was_dirty );
940+ my $ofs_delta = 0;
928941
929- for (grep { $_ -> { USE } } @in ) {
942+ for (@in ) {
930943 if ($_ -> {TYPE } ne ' hunk' ) {
931944 push @out , $_ ;
932945 next ;
933946 }
934947 my $text = $_ -> {TEXT };
935- my ($o_ofs ) = parse_hunk_header($text -> [0]);
948+ my ($o_ofs , $o_cnt , $n_ofs , $n_cnt ) =
949+ parse_hunk_header($text -> [0]);
950+ unless ($_ -> {USE }) {
951+ $ofs_delta += $o_cnt - $n_cnt ;
952+ # If this hunk has been edited then subtract
953+ # the delta that is due to the edit.
954+ if ($_ -> {OFS_DELTA }) {
955+ $ofs_delta -= $_ -> {OFS_DELTA };
956+ }
957+ next ;
958+ }
959+ if ($ofs_delta ) {
960+ $n_ofs += $ofs_delta ;
961+ $_ -> {TEXT }-> [0] = format_hunk_header($o_ofs , $o_cnt ,
962+ $n_ofs , $n_cnt );
963+ }
964+ # If this hunk was edited then adjust the offset delta
965+ # to reflect the edit.
966+ if ($_ -> {OFS_DELTA }) {
967+ $ofs_delta += $_ -> {OFS_DELTA };
968+ }
936969 if (defined $last_o_ctx &&
937970 $o_ofs <= $last_o_ctx &&
938971 !$_ -> {DIRTY } &&
@@ -1004,6 +1037,30 @@ sub color_diff {
10041037marked for applying." ),
10051038);
10061039
1040+ sub recount_edited_hunk {
1041+ local $_ ;
1042+ my ($oldtext , $newtext ) = @_ ;
1043+ my ($o_cnt , $n_cnt ) = (0, 0);
1044+ for (@{$newtext }[1..$# {$newtext }]) {
1045+ my $mode = substr ($_ , 0, 1);
1046+ if ($mode eq ' -' ) {
1047+ $o_cnt ++;
1048+ } elsif ($mode eq ' +' ) {
1049+ $n_cnt ++;
1050+ } elsif ($mode eq ' ' ) {
1051+ $o_cnt ++;
1052+ $n_cnt ++;
1053+ }
1054+ }
1055+ my ($o_ofs , undef , $n_ofs , undef ) =
1056+ parse_hunk_header($newtext -> [0]);
1057+ $newtext -> [0] = format_hunk_header($o_ofs , $o_cnt , $n_ofs , $n_cnt );
1058+ my (undef , $orig_o_cnt , undef , $orig_n_cnt ) =
1059+ parse_hunk_header($oldtext -> [0]);
1060+ # Return the change in the number of lines inserted by this hunk
1061+ return $orig_o_cnt - $orig_n_cnt - $o_cnt + $n_cnt ;
1062+ }
1063+
10071064sub edit_hunk_manually {
10081065 my ($oldtext ) = @_ ;
10091066
@@ -1102,25 +1159,32 @@ sub prompt_yesno {
11021159}
11031160
11041161sub edit_hunk_loop {
1105- my ($head , $hunk , $ix ) = @_ ;
1106- my $text = $hunk -> [$ix ]-> {TEXT };
1162+ my ($head , $hunks , $ix ) = @_ ;
1163+ my $hunk = $hunks -> [$ix ];
1164+ my $text = $hunk -> {TEXT };
11071165
11081166 while (1) {
1109- $text = edit_hunk_manually($text );
1110- if (!defined $text ) {
1167+ my $newtext = edit_hunk_manually($text );
1168+ if (!defined $newtext ) {
11111169 return undef ;
11121170 }
11131171 my $newhunk = {
1114- TEXT => $text ,
1115- TYPE => $hunk -> [ $ix ] -> {TYPE },
1172+ TEXT => $newtext ,
1173+ TYPE => $hunk -> {TYPE },
11161174 USE => 1,
11171175 DIRTY => 1,
11181176 };
1177+ $newhunk -> {OFS_DELTA } = recount_edited_hunk($text , $newtext );
1178+ # If this hunk has already been edited then add the
1179+ # offset delta of the previous edit to get the real
1180+ # delta from the original unedited hunk.
1181+ $hunk -> {OFS_DELTA } and
1182+ $newhunk -> {OFS_DELTA } += $hunk -> {OFS_DELTA };
11191183 if (diff_applies($head ,
1120- @{$hunk }[0..$ix -1],
1184+ @{$hunks }[0..$ix -1],
11211185 $newhunk ,
1122- @{$hunk }[$ix +1..$# {$hunk }])) {
1123- $newhunk -> {DISPLAY } = [color_diff(@{$text })];
1186+ @{$hunks }[$ix +1..$# {$hunks }])) {
1187+ $newhunk -> {DISPLAY } = [color_diff(@{$newtext })];
11241188 return $newhunk ;
11251189 }
11261190 else {
0 commit comments