]> git.ipfire.org Git - thirdparty/git.git/blobdiff - git-add--interactive.perl
test-ref-store: remove force-create argument for create-reflog
[thirdparty/git.git] / git-add--interactive.perl
index 52659bb74c9b8fdd5645403afbe4e715b1e089cb..bc3a1e8effa321bd40bb83170646b98ca7f2e968 100755 (executable)
@@ -30,9 +30,9 @@ my ($fraginfo_color) =
        $diff_use_color ? (
                $repo->get_color('color.diff.frag', 'cyan'),
        ) : ();
-my ($diff_plain_color) =
+my ($diff_context_color) =
        $diff_use_color ? (
-               $repo->get_color('color.diff.plain', ''),
+               $repo->get_color($repo->config('color.diff.context') ? 'color.diff.context' : 'color.diff.plain', ''),
        ) : ();
 my ($diff_old_color) =
        $diff_use_color ? (
@@ -177,7 +177,9 @@ sub run_cmd_pipe {
        } else {
                my $fh = undef;
                open($fh, '-|', @_) or die;
-               return <$fh>;
+               my @out = <$fh>;
+               close $fh || die "Cannot close @_ ($!)";
+               return @out;
        }
 }
 
@@ -224,7 +226,7 @@ my $status_head = sprintf($status_fmt, __('staged'), __('unstaged'), __('path'))
        sub get_empty_tree {
                return $empty_tree if defined $empty_tree;
 
-               $empty_tree = run_cmd_pipe(qw(git hash-object -t tree /dev/null));
+               ($empty_tree) = run_cmd_pipe(qw(git hash-object -t tree /dev/null));
                chomp $empty_tree;
                return $empty_tree;
        }
@@ -481,10 +483,8 @@ sub list_and_choose {
                my $last_lf = 0;
 
                if ($opts->{HEADER}) {
-                       if (!$opts->{LIST_FLAT}) {
-                               print "     ";
-                       }
-                       print colored $header_color, "$opts->{HEADER}\n";
+                       my $indent = $opts->{LIST_FLAT} ? "" : "     ";
+                       print colored $header_color, "$indent$opts->{HEADER}\n";
                }
                for ($i = 0; $i < @stuff; $i++) {
                        my $chosen = $chosen[$i] ? '*' : ' ';
@@ -712,7 +712,7 @@ sub parse_diff {
        if (defined $patch_mode_revision) {
                push @diff_cmd, get_diff_reference($patch_mode_revision);
        }
-       my @diff = run_cmd_pipe("git", @diff_cmd, "--", $path);
+       my @diff = run_cmd_pipe("git", @diff_cmd, qw(--no-color --), $path);
        my @colored = ();
        if ($diff_use_color) {
                my @display_cmd = ("git", @diff_cmd, qw(--color --), $path);
@@ -752,8 +752,13 @@ sub parse_diff_header {
        my $head = { TEXT => [], DISPLAY => [], TYPE => 'header' };
        my $mode = { TEXT => [], DISPLAY => [], TYPE => 'mode' };
        my $deletion = { TEXT => [], DISPLAY => [], TYPE => 'deletion' };
+       my $addition;
 
        for (my $i = 0; $i < @{$src->{TEXT}}; $i++) {
+               if ($src->{TEXT}->[$i] =~ /^new file/) {
+                       $addition = 1;
+                       $head->{TYPE} = 'addition';
+               }
                my $dest =
                   $src->{TEXT}->[$i] =~ /^(old|new) mode (\d+)$/ ? $mode :
                   $src->{TEXT}->[$i] =~ /^deleted file/ ? $deletion :
@@ -761,7 +766,7 @@ sub parse_diff_header {
                push @{$dest->{TEXT}}, $src->{TEXT}->[$i];
                push @{$dest->{DISPLAY}}, $src->{DISPLAY}->[$i];
        }
-       return ($head, $mode, $deletion);
+       return ($head, $mode, $deletion, $addition);
 }
 
 sub hunk_splittable {
@@ -1041,7 +1046,7 @@ sub color_diff {
                colored((/^@/  ? $fraginfo_color :
                         /^\+/ ? $diff_new_color :
                         /^-/  ? $diff_old_color :
-                        $diff_plain_color),
+                        $diff_context_color),
                        $_);
        } @_;
 }
@@ -1127,7 +1132,7 @@ aborted and the hunk is left unchanged.
 EOF2
        close $fh;
 
-       chomp(my $editor = run_cmd_pipe(qw(git var GIT_EDITOR)));
+       chomp(my ($editor) = run_cmd_pipe(qw(git var GIT_EDITOR)));
        system('sh', '-c', $editor.' "$@"', $editor, $hunkfile);
 
        if ($? != 0) {
@@ -1425,46 +1430,55 @@ my %patch_update_prompt_modes = (
        stage => {
                mode => N__("Stage mode change [y,n,q,a,d%s,?]? "),
                deletion => N__("Stage deletion [y,n,q,a,d%s,?]? "),
+               addition => N__("Stage addition [y,n,q,a,d%s,?]? "),
                hunk => N__("Stage this hunk [y,n,q,a,d%s,?]? "),
        },
        stash => {
                mode => N__("Stash mode change [y,n,q,a,d%s,?]? "),
                deletion => N__("Stash deletion [y,n,q,a,d%s,?]? "),
+               addition => N__("Stash addition [y,n,q,a,d%s,?]? "),
                hunk => N__("Stash this hunk [y,n,q,a,d%s,?]? "),
        },
        reset_head => {
                mode => N__("Unstage mode change [y,n,q,a,d%s,?]? "),
                deletion => N__("Unstage deletion [y,n,q,a,d%s,?]? "),
+               addition => N__("Unstage addition [y,n,q,a,d%s,?]? "),
                hunk => N__("Unstage this hunk [y,n,q,a,d%s,?]? "),
        },
        reset_nothead => {
                mode => N__("Apply mode change to index [y,n,q,a,d%s,?]? "),
                deletion => N__("Apply deletion to index [y,n,q,a,d%s,?]? "),
+               addition => N__("Apply addition to index [y,n,q,a,d%s,?]? "),
                hunk => N__("Apply this hunk to index [y,n,q,a,d%s,?]? "),
        },
        checkout_index => {
                mode => N__("Discard mode change from worktree [y,n,q,a,d%s,?]? "),
                deletion => N__("Discard deletion from worktree [y,n,q,a,d%s,?]? "),
+               addition => N__("Discard addition from worktree [y,n,q,a,d%s,?]? "),
                hunk => N__("Discard this hunk from worktree [y,n,q,a,d%s,?]? "),
        },
        checkout_head => {
                mode => N__("Discard mode change from index and worktree [y,n,q,a,d%s,?]? "),
                deletion => N__("Discard deletion from index and worktree [y,n,q,a,d%s,?]? "),
+               addition => N__("Discard addition from index and worktree [y,n,q,a,d%s,?]? "),
                hunk => N__("Discard this hunk from index and worktree [y,n,q,a,d%s,?]? "),
        },
        checkout_nothead => {
                mode => N__("Apply mode change to index and worktree [y,n,q,a,d%s,?]? "),
                deletion => N__("Apply deletion to index and worktree [y,n,q,a,d%s,?]? "),
+               addition => N__("Apply addition to index and worktree [y,n,q,a,d%s,?]? "),
                hunk => N__("Apply this hunk to index and worktree [y,n,q,a,d%s,?]? "),
        },
        worktree_head => {
                mode => N__("Discard mode change from worktree [y,n,q,a,d%s,?]? "),
                deletion => N__("Discard deletion from worktree [y,n,q,a,d%s,?]? "),
+               addition => N__("Discard addition from worktree [y,n,q,a,d%s,?]? "),
                hunk => N__("Discard this hunk from worktree [y,n,q,a,d%s,?]? "),
        },
        worktree_nothead => {
                mode => N__("Apply mode change to worktree [y,n,q,a,d%s,?]? "),
                deletion => N__("Apply deletion to worktree [y,n,q,a,d%s,?]? "),
+               addition => N__("Apply addition to worktree [y,n,q,a,d%s,?]? "),
                hunk => N__("Apply this hunk to worktree [y,n,q,a,d%s,?]? "),
        },
 );
@@ -1474,7 +1488,7 @@ sub patch_update_file {
        my ($ix, $num);
        my $path = shift;
        my ($head, @hunk) = parse_diff($path);
-       ($head, my $mode, my $deletion) = parse_diff_header($head);
+       ($head, my $mode, my $deletion, my $addition) = parse_diff_header($head);
        for (@{$head->{DISPLAY}}) {
                print;
        }
@@ -1497,6 +1511,7 @@ sub patch_update_file {
                my ($prev, $next, $other, $undecided, $i);
                $other = '';
 
+               last if ($ix and !$num);
                if ($num <= $ix) {
                        $ix = 0;
                }
@@ -1529,35 +1544,51 @@ sub patch_update_file {
                                last;
                        }
                }
-               last if (!$undecided);
+               last if (!$undecided && ($num || !$addition));
 
-               if ($hunk[$ix]{TYPE} eq 'hunk' &&
-                   hunk_splittable($hunk[$ix]{TEXT})) {
-                       $other .= ',s';
-               }
-               if ($hunk[$ix]{TYPE} eq 'hunk') {
-                       $other .= ',e';
-               }
-               for (@{$hunk[$ix]{DISPLAY}}) {
-                       print;
+               if ($num) {
+                       if ($hunk[$ix]{TYPE} eq 'hunk' &&
+                           hunk_splittable($hunk[$ix]{TEXT})) {
+                               $other .= ',s';
+                       }
+                       if ($hunk[$ix]{TYPE} eq 'hunk') {
+                               $other .= ',e';
+                       }
+                       for (@{$hunk[$ix]{DISPLAY}}) {
+                               print;
+                       }
                }
-               print colored $prompt_color, "(", ($ix+1), "/$num) ",
-                       sprintf(__($patch_update_prompt_modes{$patch_mode}{$hunk[$ix]{TYPE}}), $other);
+               my $type = $num ? $hunk[$ix]{TYPE} : $head->{TYPE};
+               print colored $prompt_color, "(", ($ix+1), "/", ($num ? $num : 1), ") ",
+                       sprintf(__($patch_update_prompt_modes{$patch_mode}{$type}), $other);
 
                my $line = prompt_single_character;
                last unless defined $line;
                if ($line) {
                        if ($line =~ /^y/i) {
-                               $hunk[$ix]{USE} = 1;
+                               if ($num) {
+                                       $hunk[$ix]{USE} = 1;
+                               } else {
+                                       $head->{USE} = 1;
+                               }
                        }
                        elsif ($line =~ /^n/i) {
-                               $hunk[$ix]{USE} = 0;
+                               if ($num) {
+                                       $hunk[$ix]{USE} = 0;
+                               } else {
+                                       $head->{USE} = 0;
+                               }
                        }
                        elsif ($line =~ /^a/i) {
-                               while ($ix < $num) {
-                                       if (!defined $hunk[$ix]{USE}) {
-                                               $hunk[$ix]{USE} = 1;
+                               if ($num) {
+                                       while ($ix < $num) {
+                                               if (!defined $hunk[$ix]{USE}) {
+                                                       $hunk[$ix]{USE} = 1;
+                                               }
+                                               $ix++;
                                        }
+                               } else {
+                                       $head->{USE} = 1;
                                        $ix++;
                                }
                                next;
@@ -1594,19 +1625,28 @@ sub patch_update_file {
                                next;
                        }
                        elsif ($line =~ /^d/i) {
-                               while ($ix < $num) {
-                                       if (!defined $hunk[$ix]{USE}) {
-                                               $hunk[$ix]{USE} = 0;
+                               if ($num) {
+                                       while ($ix < $num) {
+                                               if (!defined $hunk[$ix]{USE}) {
+                                                       $hunk[$ix]{USE} = 0;
+                                               }
+                                               $ix++;
                                        }
+                               } else {
+                                       $head->{USE} = 0;
                                        $ix++;
                                }
                                next;
                        }
                        elsif ($line =~ /^q/i) {
-                               for ($i = 0; $i < $num; $i++) {
-                                       if (!defined $hunk[$i]{USE}) {
-                                               $hunk[$i]{USE} = 0;
+                               if ($num) {
+                                       for ($i = 0; $i < $num; $i++) {
+                                               if (!defined $hunk[$i]{USE}) {
+                                                       $hunk[$i]{USE} = 0;
+                                               }
                                        }
+                               } elsif (!defined $head->{USE}) {
+                                       $head->{USE} = 0;
                                }
                                $quit = 1;
                                last;
@@ -1724,7 +1764,7 @@ sub patch_update_file {
                }
        }
 
-       @hunk = coalesce_overlapping_hunks(@hunk);
+       @hunk = coalesce_overlapping_hunks(@hunk) if ($num);
 
        my $n_lofs = 0;
        my @result = ();
@@ -1734,7 +1774,7 @@ sub patch_update_file {
                }
        }
 
-       if (@result) {
+       if (@result or $head->{USE}) {
                my @patch = reassemble_patch($head->{TEXT}, @result);
                my $apply_routine = $patch_mode_flavour{APPLY};
                &$apply_routine(@patch);
@@ -1788,6 +1828,13 @@ sub process_args {
                                $arg = shift @ARGV or die __("missing --");
                                if ($arg ne '--') {
                                        $patch_mode_revision = $arg;
+
+                                       # NEEDSWORK: Instead of comparing to the literal "HEAD",
+                                       # compare the commit objects instead so that other ways of
+                                       # saying the same thing (such as "@") are also handled
+                                       # appropriately.
+                                       #
+                                       # This applies to the cases below too.
                                        $patch_mode = ($arg eq 'HEAD' ?
                                                       'reset_head' : 'reset_nothead');
                                        $arg = shift @ARGV or die __("missing --");