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 <gitster@pobox.com>
Junio C Hamano committed
May 16, 2009 at 10:48 UTC
7a26e653929025e11e689bc7d98365c9a0107dc9
2 files changed
+96
-2
git-add--interactive.perl
+95
-1
@@ -767,6 +767,96 @@ sub split_hunk {
767
return @split;
768
}
769
770
+sub find_last_o_ctx {
771
+ my ($it) = @_;
772
+ my $text = $it->{TEXT};
773
+ my ($o_ofs, $o_cnt) = parse_hunk_header($text->[0]);
774
+ my $i = @{$text};
775
+ my $last_o_ctx = $o_ofs + $o_cnt;
776
+ while (0 < --$i) {
777
+ my $line = $text->[$i];
778
+ if ($line =~ /^ /) {
779
+ $last_o_ctx--;
780
+ next;
781
+ }
782
+ last;
783
+ }
784
+ return $last_o_ctx;
785
+}
786
+
787
+sub merge_hunk {
788
+ my ($prev, $this) = @_;
789
+ my ($o0_ofs, $o0_cnt, $n0_ofs, $n0_cnt) =
790
+ parse_hunk_header($prev->{TEXT}[0]);
791
+ my ($o1_ofs, $o1_cnt, $n1_ofs, $n1_cnt) =
792
+ parse_hunk_header($this->{TEXT}[0]);
793
+
794
+ my (@line, $i, $ofs, $o_cnt, $n_cnt);
795
+ $ofs = $o0_ofs;
796
+ $o_cnt = $n_cnt = 0;
797
+ for ($i = 1; $i < @{$prev->{TEXT}}; $i++) {
798
+ my $line = $prev->{TEXT}[$i];
799
+ if ($line =~ /^\+/) {
800
+ $n_cnt++;
801
+ push @line, $line;
802
+ next;
803
+ }
804
+
805
+ last if ($o1_ofs <= $ofs);
806
+
807
+ $o_cnt++;
808
+ $ofs++;
809
+ if ($line =~ /^ /) {
810
+ $n_cnt++;
811
+ }
812
+ push @line, $line;
813
+ }
814
+
815
+ for ($i = 1; $i < @{$this->{TEXT}}; $i++) {
816
+ my $line = $this->{TEXT}[$i];
817
+ if ($line =~ /^\+/) {
818
+ $n_cnt++;
819
+ push @line, $line;
820
+ next;
821
+ }
822
+ $ofs++;
823
+ $o_cnt++;
824
+ if ($line =~ /^ /) {
825
+ $n_cnt++;
826
+ }
827
+ push @line, $line;
828
+ }
829
+ my $head = ("@@ -$o0_ofs" .
830
+ (($o_cnt != 1) ? ",$o_cnt" : '') .
831
+ " +$n0_ofs" .
832
+ (($n_cnt != 1) ? ",$n_cnt" : '') .
833
+ " @@\n");
834
+ @{$prev->{TEXT}} = ($head, @line);
835
+}
836
+
837
+sub coalesce_overlapping_hunks {
838
+ my (@in) = @_;
839
+ my @out = ();
840
+
841
+ my ($last_o_ctx, $last_was_dirty);
842
+
843
+ for (grep { $_->{USE} } @in) {
844
+ my $text = $_->{TEXT};
845
+ my ($o_ofs) = parse_hunk_header($text->[0]);
846
+ if (defined $last_o_ctx &&
847
+ $o_ofs <= $last_o_ctx &&
848
+ !$_->{DIRTY} &&
849
+ !$last_was_dirty) {
850
+ merge_hunk($out[-1], $_);
851
+ }
852
+ else {
853
+ push @out, $_;
854
+ }
855
+ $last_o_ctx = find_last_o_ctx($out[-1]);
856
+ $last_was_dirty = $_->{DIRTY};
857
+ }
858
+ return @out;
859
+}
860
861
sub color_diff {
862
return map {
@@ -878,7 +968,8 @@ sub edit_hunk_loop {
968
my $newhunk = {
969
TEXT => $text,
970
TYPE => $hunk->[$ix]->{TYPE},
881
- USE => 1
971
+ USE => 1,
972
+ DIRTY => 1,
973
};
974
if (diff_applies($head,
975
@{$hunk}[0..$ix-1],
@@ -1210,6 +1301,8 @@ sub patch_update_file {
1301
}
1302
}
1303
1304
+ @hunk = coalesce_overlapping_hunks(@hunk);
1305
+
1306
my $n_lofs = 0;
1307
my @result = ();
1308
for (@hunk) {
@@ -1224,6 +1317,7 @@ sub patch_update_file {
1317
open $fh, '| git apply --cached --recount';
1318
for (@{$head->{TEXT}}, @result) {
1319
print $fh $_;
1320
+ print STDERR $_;
1321
}
1322
if (!close $fh) {
1323
for (@{$head->{TEXT}}, @result) {
t/t3701-add-interactive.sh
+1
-1
@@ -189,7 +189,7 @@ index b6f2c08..61b9053 100755
189
+lastline
190
EOF
191
# Test splitting the first patch, then adding both
192
-test_expect_failure 'add first line works' '
192
+test_expect_success 'add first line works' '
193
git commit -am "clear local changes" &&
194
git apply patch &&
195
(echo s; echo y; echo y) | git add -p file &&