diff options
-rwxr-xr-x | git-add--interactive.perl | 59 | ||||
-rwxr-xr-x | t/t3701-add-interactive.sh | 2 |
2 files changed, 51 insertions, 10 deletions
diff --git a/git-add--interactive.perl b/git-add--interactive.perl index 6f6a21dc11..b5f01160c5 100755 --- a/git-add--interactive.perl +++ b/git-add--interactive.perl @@ -938,6 +938,11 @@ sub coalesce_overlapping_hunks { parse_hunk_header($text->[0]); unless ($_->{USE}) { $ofs_delta += $o_cnt - $n_cnt; + # If this hunk has been edited then subtract + # the delta that is due to the edit. + if ($_->{OFS_DELTA}) { + $ofs_delta -= $_->{OFS_DELTA}; + } next; } if ($ofs_delta) { @@ -945,6 +950,11 @@ sub coalesce_overlapping_hunks { $_->{TEXT}->[0] = format_hunk_header($o_ofs, $o_cnt, $n_ofs, $n_cnt); } + # If this hunk was edited then adjust the offset delta + # to reflect the edit. + if ($_->{OFS_DELTA}) { + $ofs_delta += $_->{OFS_DELTA}; + } if (defined $last_o_ctx && $o_ofs <= $last_o_ctx && !$_->{DIRTY} && @@ -1016,6 +1026,30 @@ marked for discarding."), marked for applying."), ); +sub recount_edited_hunk { + local $_; + my ($oldtext, $newtext) = @_; + my ($o_cnt, $n_cnt) = (0, 0); + for (@{$newtext}[1..$#{$newtext}]) { + my $mode = substr($_, 0, 1); + if ($mode eq '-') { + $o_cnt++; + } elsif ($mode eq '+') { + $n_cnt++; + } elsif ($mode eq ' ') { + $o_cnt++; + $n_cnt++; + } + } + my ($o_ofs, undef, $n_ofs, undef) = + parse_hunk_header($newtext->[0]); + $newtext->[0] = format_hunk_header($o_ofs, $o_cnt, $n_ofs, $n_cnt); + my (undef, $orig_o_cnt, undef, $orig_n_cnt) = + parse_hunk_header($oldtext->[0]); + # Return the change in the number of lines inserted by this hunk + return $orig_o_cnt - $orig_n_cnt - $o_cnt + $n_cnt; +} + sub edit_hunk_manually { my ($oldtext) = @_; @@ -1114,25 +1148,32 @@ sub prompt_yesno { } sub edit_hunk_loop { - my ($head, $hunk, $ix) = @_; - my $text = $hunk->[$ix]->{TEXT}; + my ($head, $hunks, $ix) = @_; + my $hunk = $hunks->[$ix]; + my $text = $hunk->{TEXT}; while (1) { - $text = edit_hunk_manually($text); - if (!defined $text) { + my $newtext = edit_hunk_manually($text); + if (!defined $newtext) { return undef; } my $newhunk = { - TEXT => $text, - TYPE => $hunk->[$ix]->{TYPE}, + TEXT => $newtext, + TYPE => $hunk->{TYPE}, USE => 1, DIRTY => 1, }; + $newhunk->{OFS_DELTA} = recount_edited_hunk($text, $newtext); + # If this hunk has already been edited then add the + # offset delta of the previous edit to get the real + # delta from the original unedited hunk. + $hunk->{OFS_DELTA} and + $newhunk->{OFS_DELTA} += $hunk->{OFS_DELTA}; if (diff_applies($head, - @{$hunk}[0..$ix-1], + @{$hunks}[0..$ix-1], $newhunk, - @{$hunk}[$ix+1..$#{$hunk}])) { - $newhunk->{DISPLAY} = [color_diff(@{$text})]; + @{$hunks}[$ix+1..$#{$hunks}])) { + $newhunk->{DISPLAY} = [color_diff(@{$newtext})]; return $newhunk; } else { diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index 6f18a92486..24ed3f4a22 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -504,7 +504,7 @@ test_expect_success 'add -p works with pathological context lines' ' test_cmp expected-1 actual ' -test_expect_failure 'add -p patch editing works with pathological context lines' ' +test_expect_success 'add -p patch editing works with pathological context lines' ' git reset && # n q q below is in case edit fails printf "%s\n" e y n q q | |