Fix a pathological case in git detecting proper renames
[gitweb.git] / git-add--interactive.perl
index 7921cde8cbd3b58f1d7222e9828bf85e10f363e3..fb1e92a7664f77aa5ca4ca30b4711bafaf155466 100755 (executable)
@@ -37,10 +37,7 @@ sub list_untracked {
                chomp $_;
                $_;
        }
-       run_cmd_pipe(qw(git ls-files --others
-                       --exclude-per-directory=.gitignore),
-                    "--exclude-from=$GIT_DIR/info/exclude",
-                    '--', @_);
+       run_cmd_pipe(qw(git ls-files --others --exclude-standard --), @_);
 }
 
 my $status_fmt = '%12s %12s %s';
@@ -213,9 +210,13 @@ sub list_and_choose {
                        print ">> ";
                }
                my $line = <STDIN>;
-               last if (!$line);
+               if (!$line) {
+                       print "\n";
+                       $opts->{ON_EOF}->() if $opts->{ON_EOF};
+                       last;
+               }
                chomp $line;
-               my $donesomething = 0;
+               last if $line eq '';
                for my $choice (split(/[\s,]+/, $line)) {
                        my $choose = 1;
                        my ($bottom, $top);
@@ -247,12 +248,11 @@ sub list_and_choose {
                                next TOPLOOP;
                        }
                        for ($i = $bottom-1; $i <= $top-1; $i++) {
-                               next if (@stuff <= $i);
+                               next if (@stuff <= $i || $i < 0);
                                $chosen[$i] = $choose;
-                               $donesomething++;
                        }
                }
-               last if (!$donesomething || $opts->{IMMEDIATE});
+               last if ($opts->{IMMEDIATE});
        }
        for ($i = 0; $i < @stuff; $i++) {
                if ($chosen[$i]) {
@@ -357,7 +357,9 @@ sub hunk_splittable {
 sub parse_hunk_header {
        my ($line) = @_;
        my ($o_ofs, $o_cnt, $n_ofs, $n_cnt) =
-           $line =~ /^@@ -(\d+)(?:,(\d+)) \+(\d+)(?:,(\d+)) @@/;
+           $line =~ /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/;
+       $o_cnt = 1 unless defined $o_cnt;
+       $n_cnt = 1 unless defined $n_cnt;
        return ($o_ofs, $o_cnt, $n_ofs, $n_cnt);
 }
 
@@ -369,9 +371,8 @@ sub split_hunk {
        # it can be split, but we would need to take care of
        # overlaps later.
 
-       my ($o_ofs, $o_cnt, $n_ofs, $n_cnt) = parse_hunk_header($text->[0]);
+       my ($o_ofs, undef, $n_ofs) = parse_hunk_header($text->[0]);
        my $hunk_start = 1;
-       my $next_hunk_start;
 
       OUTER:
        while (1) {
@@ -438,8 +439,8 @@ sub split_hunk {
        for my $hunk (@split) {
                $o_ofs = $hunk->{OLD};
                $n_ofs = $hunk->{NEW};
-               $o_cnt = $hunk->{OCNT};
-               $n_cnt = $hunk->{NCNT};
+               my $o_cnt = $hunk->{OCNT};
+               my $n_cnt = $hunk->{NCNT};
 
                my $head = ("@@ -$o_ofs" .
                            (($o_cnt != 1) ? ",$o_cnt" : '') .
@@ -454,7 +455,7 @@ sub split_hunk {
 sub find_last_o_ctx {
        my ($it) = @_;
        my $text = $it->{TEXT};
-       my ($o_ofs, $o_cnt, $n_ofs, $n_cnt) = parse_hunk_header($text->[0]);
+       my ($o_ofs, $o_cnt) = parse_hunk_header($text->[0]);
        my $i = @{$text};
        my $last_o_ctx = $o_ofs + $o_cnt;
        while (0 < --$i) {
@@ -526,8 +527,7 @@ sub coalesce_overlapping_hunks {
 
        for (grep { $_->{USE} } @in) {
                my $text = $_->{TEXT};
-               my ($o_ofs, $o_cnt, $n_ofs, $n_cnt) =
-                   parse_hunk_header($text->[0]);
+               my ($o_ofs) = parse_hunk_header($text->[0]);
                if (defined $last_o_ctx &&
                    $o_ofs <= $last_o_ctx) {
                        merge_hunk($out[-1], $_);
@@ -564,10 +564,12 @@ sub patch_update_cmd {
                                     IMMEDIATE => 1,
                                     HEADER => $status_head, },
                                   @mods);
-       return if (!$it);
+       patch_update_file($it->{VALUE}) if ($it);
+}
 
+sub patch_update_file {
        my ($ix, $num);
-       my $path = $it->{VALUE};
+       my $path = shift;
        my ($head, @hunk) = parse_diff($path);
        for (@{$head->{TEXT}}) {
                print;
@@ -694,7 +696,7 @@ sub patch_update_cmd {
 
        @hunk = coalesce_overlapping_hunks(@hunk);
 
-       my ($o_lofs, $n_lofs) = (0, 0);
+       my $n_lofs = 0;
        my @result = ();
        for (@hunk) {
                my $text = $_->{TEXT};
@@ -702,9 +704,6 @@ sub patch_update_cmd {
                    parse_hunk_header($text->[0]);
 
                if (!$_->{USE}) {
-                       if (!defined $o_cnt) { $o_cnt = 1; }
-                       if (!defined $n_cnt) { $n_cnt = 1; }
-
                        # We would have added ($n_cnt - $o_cnt) lines
                        # to the postimage if we were to use this hunk,
                        # but we didn't.  So the line number that the next
@@ -716,10 +715,10 @@ sub patch_update_cmd {
                        if ($n_lofs) {
                                $n_ofs += $n_lofs;
                                $text->[0] = ("@@ -$o_ofs" .
-                                             ((defined $o_cnt)
+                                             (($o_cnt != 1)
                                               ? ",$o_cnt" : '') .
                                              " +$n_ofs" .
-                                             ((defined $n_cnt)
+                                             (($n_cnt != 1)
                                               ? ",$n_cnt" : '') .
                                              " @@\n");
                        }
@@ -791,6 +790,7 @@ sub main_loop {
                                             SINGLETON => 1,
                                             LIST_FLAT => 4,
                                             HEADER => '*** Commands ***',
+                                            ON_EOF => \&quit_cmd,
                                             IMMEDIATE => 1 }, @cmd);
                if ($it) {
                        eval {
@@ -803,8 +803,6 @@ sub main_loop {
        }
 }
 
-my @z;
-
 refresh();
 status_cmd();
 main_loop();