diff options
Diffstat (limited to 'git-add--interactive.perl')
| -rwxr-xr-x | git-add--interactive.perl | 99 | 
1 files changed, 98 insertions, 1 deletions
| diff --git a/git-add--interactive.perl b/git-add--interactive.perl index f6e536ece3..06f70602cc 100755 --- a/git-add--interactive.perl +++ b/git-add--interactive.perl @@ -767,6 +767,100 @@ 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) { +		if ($_->{TYPE} ne 'hunk') { +			push @out, $_; +			next; +		} +		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 +972,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 +1305,8 @@ sub patch_update_file {  		}  	} +	@hunk = coalesce_overlapping_hunks(@hunk); +  	my $n_lofs = 0;  	my @result = ();  	for (@hunk) { | 
