sha1_object_info_extended(): expose a bit more info
[gitweb.git] / git-add--interactive.perl
index cd43c3491260cb2aa51f0d19fd18ab66e4ad8217..4f08fe704bbaff64613ab07630a71da8bf8bbca0 100755 (executable)
@@ -1,6 +1,8 @@
-#!/usr/bin/perl -w
+#!/usr/bin/perl
 
+use 5.008;
 use strict;
+use warnings;
 use Git;
 
 binmode(STDOUT, ":raw");
@@ -87,6 +89,7 @@ sub colored {
                TARGET => '',
                PARTICIPLE => 'staging',
                FILTER => 'file-only',
+               IS_REVERSE => 0,
        },
        'stash' => {
                DIFF => 'diff-index -p HEAD',
@@ -96,6 +99,7 @@ sub colored {
                TARGET => '',
                PARTICIPLE => 'stashing',
                FILTER => undef,
+               IS_REVERSE => 0,
        },
        'reset_head' => {
                DIFF => 'diff-index -p --cached',
@@ -105,6 +109,7 @@ sub colored {
                TARGET => '',
                PARTICIPLE => 'unstaging',
                FILTER => 'index-only',
+               IS_REVERSE => 1,
        },
        'reset_nothead' => {
                DIFF => 'diff-index -R -p --cached',
@@ -114,6 +119,7 @@ sub colored {
                TARGET => ' to index',
                PARTICIPLE => 'applying',
                FILTER => 'index-only',
+               IS_REVERSE => 0,
        },
        'checkout_index' => {
                DIFF => 'diff-files -p',
@@ -123,6 +129,7 @@ sub colored {
                TARGET => ' from worktree',
                PARTICIPLE => 'discarding',
                FILTER => 'file-only',
+               IS_REVERSE => 1,
        },
        'checkout_head' => {
                DIFF => 'diff-index -p',
@@ -132,6 +139,7 @@ sub colored {
                TARGET => ' from index and worktree',
                PARTICIPLE => 'discarding',
                FILTER => undef,
+               IS_REVERSE => 1,
        },
        'checkout_nothead' => {
                DIFF => 'diff-index -R -p',
@@ -141,6 +149,7 @@ sub colored {
                TARGET => ' to index and worktree',
                PARTICIPLE => 'applying',
                FILTER => undef,
+               IS_REVERSE => 0,
        },
 );
 
@@ -696,7 +705,7 @@ sub add_untracked_cmd {
 sub run_git_apply {
        my $cmd = shift;
        my $fh;
-       open $fh, '| git ' . $cmd;
+       open $fh, '| git ' . $cmd . " --recount --allow-overlap";
        print $fh @_;
        return close $fh;
 }
@@ -957,6 +966,28 @@ sub coalesce_overlapping_hunks {
        return @out;
 }
 
+sub reassemble_patch {
+       my $head = shift;
+       my @patch;
+
+       # Include everything in the header except the beginning of the diff.
+       push @patch, (grep { !/^[-+]{3}/ } @$head);
+
+       # Then include any headers from the hunk lines, which must
+       # come before any actual hunk.
+       while (@_ && $_[0] !~ /^@/) {
+               push @patch, shift;
+       }
+
+       # Then begin the diff.
+       push @patch, grep { /^[-+]{3}/ } @$head;
+
+       # And then the actual hunks.
+       push @patch, @_;
+
+       return @patch;
+}
+
 sub color_diff {
        return map {
                colored((/^@/  ? $fraginfo_color :
@@ -977,10 +1008,12 @@ sub edit_hunk_manually {
        print $fh "# Manual hunk edit mode -- see bottom for a quick guide\n";
        print $fh @$oldtext;
        my $participle = $patch_mode_flavour{PARTICIPLE};
+       my $is_reverse = $patch_mode_flavour{IS_REVERSE};
+       my ($remove_plus, $remove_minus) = $is_reverse ? ('-', '+') : ('+', '-');
        print $fh <<EOF;
 # ---
-# To remove '-' lines, make them ' ' lines (context).
-# To remove '+' lines, delete them.
+# To remove '$remove_minus' lines, make them ' ' lines (context).
+# To remove '$remove_plus' lines, delete them.
 # Lines starting with # will be removed.
 #
 # If the patch applies cleanly, the edited hunk will immediately be
@@ -1017,7 +1050,7 @@ sub edit_hunk_manually {
 
 sub diff_applies {
        my $fh;
-       return run_git_apply($patch_mode_flavour{APPLY_CHECK} . ' --recount --check',
+       return run_git_apply($patch_mode_flavour{APPLY_CHECK} . ' --check',
                             map { @{$_->{TEXT}} } @_);
 }
 
@@ -1089,9 +1122,9 @@ sub help_patch_cmd {
        print colored $help_color, <<EOF ;
 y - $verb this hunk$target
 n - do not $verb this hunk$target
-q - quit, do not $verb this hunk nor any of the remaining ones
-a - $verb this and all the remaining hunks in the file
-d - do not $verb this hunk nor any of the remaining hunks in the file
+q - quit; do not $verb this hunk nor any of the remaining ones
+a - $verb this hunk and all later hunks in the file
+d - do not $verb this hunk nor any of the later hunks in the file
 g - select a hunk to go to
 / - search for a hunk matching the given regex
 j - leave this hunk undecided, see next undecided hunk
@@ -1106,7 +1139,7 @@ sub help_patch_cmd {
 
 sub apply_patch {
        my $cmd = shift;
-       my $ret = run_git_apply $cmd . ' --recount', @_;
+       my $ret = run_git_apply $cmd, @_;
        if (!$ret) {
                print STDERR @_;
        }
@@ -1115,17 +1148,17 @@ sub apply_patch {
 
 sub apply_patch_for_checkout_commit {
        my $reverse = shift;
-       my $applies_index = run_git_apply 'apply '.$reverse.' --cached --recount --check', @_;
-       my $applies_worktree = run_git_apply 'apply '.$reverse.' --recount --check', @_;
+       my $applies_index = run_git_apply 'apply '.$reverse.' --cached --check', @_;
+       my $applies_worktree = run_git_apply 'apply '.$reverse.' --check', @_;
 
        if ($applies_worktree && $applies_index) {
-               run_git_apply 'apply '.$reverse.' --cached --recount', @_;
-               run_git_apply 'apply '.$reverse.' --recount', @_;
+               run_git_apply 'apply '.$reverse.' --cached', @_;
+               run_git_apply 'apply '.$reverse, @_;
                return 1;
        } elsif (!$applies_index) {
                print colored $error_color, "The selected hunks do not apply to the index!\n";
                if (prompt_yesno "Apply them to the worktree anyway? ") {
-                       return run_git_apply 'apply '.$reverse.' --recount', @_;
+                       return run_git_apply 'apply '.$reverse, @_;
                } else {
                        print colored $error_color, "Nothing was applied.\n";
                        return 0;
@@ -1333,14 +1366,13 @@ sub patch_update_file {
                                next;
                        }
                        elsif ($line =~ /^q/i) {
-                               while ($ix < $num) {
-                                       if (!defined $hunk[$ix]{USE}) {
-                                               $hunk[$ix]{USE} = 0;
+                               for ($i = 0; $i < $num; $i++) {
+                                       if (!defined $hunk[$i]{USE}) {
+                                               $hunk[$i]{USE} = 0;
                                        }
-                                       $ix++;
                                }
                                $quit = 1;
-                               next;
+                               last;
                        }
                        elsif ($line =~ m|^/(.*)|) {
                                my $regex = $1;
@@ -1453,7 +1485,7 @@ sub patch_update_file {
 
        if (@result) {
                my $fh;
-               my @patch = (@{$head->{TEXT}}, @result);
+               my @patch = reassemble_patch($head->{TEXT}, @result);
                my $apply_routine = $patch_mode_flavour{APPLY};
                &$apply_routine(@patch);
                refresh();