From f67182bf65b01290a9544e9599ea8255e657e567 Mon Sep 17 00:00:00 2001 From: Matt Graham Date: Fri, 15 May 2009 23:10:19 -0400 Subject: Splitting a hunk that adds a line at the top fails in "add -p" Splitting a hunk into two in add -p doesn't work for a diff that adds a new line at the top of the file with other add in the same hunk. Signed-off-by: Matthew Graham Signed-off-by: Junio C Hamano --- t/t3701-add-interactive.sh | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index dfc65601aa..9999fcd4b6 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -165,4 +165,36 @@ test_expect_success FILEMODE 'stage mode but not hunk' ' # end of tests disabled when filemode is not usable +# Write the patch file with a new line at the top and bottom +cat >patch <expected < diff && + test_cmp expected diff +' + test_done -- cgit v1.2.1 From 7a26e653929025e11e689bc7d98365c9a0107dc9 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 16 May 2009 10:48:23 -0700 Subject: Revert "git-add--interactive: remove hunk coalescing" This reverts commit 0beee4c6dec15292415e3d56075c16a76a22af54 but with a bit of twist, as we have added "edit hunk manually" hack and we cannot rely on the original line numbers of the hunks that were manually edited. Signed-off-by: Junio C Hamano --- git-add--interactive.perl | 96 +++++++++++++++++++++++++++++++++++++++++++++- t/t3701-add-interactive.sh | 2 +- 2 files changed, 96 insertions(+), 2 deletions(-) diff --git a/git-add--interactive.perl b/git-add--interactive.perl index f6e536ece3..a06172c69f 100755 --- a/git-add--interactive.perl +++ b/git-add--interactive.perl @@ -767,6 +767,96 @@ sub split_hunk { return @split; } +sub find_last_o_ctx { + my ($it) = @_; + my $text = $it->{TEXT}; + my ($o_ofs, $o_cnt) = parse_hunk_header($text->[0]); + my $i = @{$text}; + my $last_o_ctx = $o_ofs + $o_cnt; + while (0 < --$i) { + my $line = $text->[$i]; + if ($line =~ /^ /) { + $last_o_ctx--; + next; + } + last; + } + return $last_o_ctx; +} + +sub merge_hunk { + my ($prev, $this) = @_; + my ($o0_ofs, $o0_cnt, $n0_ofs, $n0_cnt) = + parse_hunk_header($prev->{TEXT}[0]); + my ($o1_ofs, $o1_cnt, $n1_ofs, $n1_cnt) = + parse_hunk_header($this->{TEXT}[0]); + + my (@line, $i, $ofs, $o_cnt, $n_cnt); + $ofs = $o0_ofs; + $o_cnt = $n_cnt = 0; + for ($i = 1; $i < @{$prev->{TEXT}}; $i++) { + my $line = $prev->{TEXT}[$i]; + if ($line =~ /^\+/) { + $n_cnt++; + push @line, $line; + next; + } + + last if ($o1_ofs <= $ofs); + + $o_cnt++; + $ofs++; + if ($line =~ /^ /) { + $n_cnt++; + } + push @line, $line; + } + + for ($i = 1; $i < @{$this->{TEXT}}; $i++) { + my $line = $this->{TEXT}[$i]; + if ($line =~ /^\+/) { + $n_cnt++; + push @line, $line; + next; + } + $ofs++; + $o_cnt++; + if ($line =~ /^ /) { + $n_cnt++; + } + push @line, $line; + } + my $head = ("@@ -$o0_ofs" . + (($o_cnt != 1) ? ",$o_cnt" : '') . + " +$n0_ofs" . + (($n_cnt != 1) ? ",$n_cnt" : '') . + " @@\n"); + @{$prev->{TEXT}} = ($head, @line); +} + +sub coalesce_overlapping_hunks { + my (@in) = @_; + my @out = (); + + my ($last_o_ctx, $last_was_dirty); + + for (grep { $_->{USE} } @in) { + my $text = $_->{TEXT}; + my ($o_ofs) = parse_hunk_header($text->[0]); + if (defined $last_o_ctx && + $o_ofs <= $last_o_ctx && + !$_->{DIRTY} && + !$last_was_dirty) { + merge_hunk($out[-1], $_); + } + else { + push @out, $_; + } + $last_o_ctx = find_last_o_ctx($out[-1]); + $last_was_dirty = $_->{DIRTY}; + } + return @out; +} sub color_diff { return map { @@ -878,7 +968,8 @@ sub edit_hunk_loop { my $newhunk = { TEXT => $text, TYPE => $hunk->[$ix]->{TYPE}, - USE => 1 + USE => 1, + DIRTY => 1, }; if (diff_applies($head, @{$hunk}[0..$ix-1], @@ -1210,6 +1301,8 @@ sub patch_update_file { } } + @hunk = coalesce_overlapping_hunks(@hunk); + my $n_lofs = 0; my @result = (); for (@hunk) { @@ -1224,6 +1317,7 @@ sub patch_update_file { open $fh, '| git apply --cached --recount'; for (@{$head->{TEXT}}, @result) { print $fh $_; + print STDERR $_; } if (!close $fh) { for (@{$head->{TEXT}}, @result) { diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index 9999fcd4b6..5cdb83d28c 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -189,7 +189,7 @@ index b6f2c08..61b9053 100755 +lastline EOF # Test splitting the first patch, then adding both -test_expect_failure 'add first line works' ' +test_expect_success 'add first line works' ' git commit -am "clear local changes" && git apply patch && (echo s; echo y; echo y) | git add -p file && -- cgit v1.2.1 From 32a90233d147bd697b338326bd1fabf9edc3f1fe Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Mon, 25 May 2009 14:07:55 +0200 Subject: t3701: ensure correctly set up repository after skipped tests There are two tests that are skipped if file modes are not obeyed by the file system. In this case, the subsequent test failed because the repository was in an unexpected state. This corrects it. Signed-off-by: Johannes Sixt Signed-off-by: Junio C Hamano --- t/t3701-add-interactive.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index 5cdb83d28c..fd2a55a5c2 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -165,6 +165,12 @@ test_expect_success FILEMODE 'stage mode but not hunk' ' # end of tests disabled when filemode is not usable +test_expect_success 'setup again' ' + git reset --hard && + test_chmod +x file && + echo content >>file +' + # Write the patch file with a new line at the top and bottom cat >patch <