diff --git a/apply.c b/apply.c index b5485ef6c9..fab44322c5 100644 --- a/apply.c +++ b/apply.c @@ -2661,6 +2661,16 @@ static int find_pos(struct apply_state *state, unsigned long backwards, forwards, current; int backwards_lno, forwards_lno, current_lno; + /* + * When running with --allow-overlap, it is possible that a hunk is + * seen that pretends to start at the beginning (but no longer does), + * and that *still* needs to match the end. So trust `match_end` more + * than `match_beginning`. + */ + if (state->allow_overlap && match_beginning && match_end && + img->nr - preimage->nr != 0) + match_beginning = 0; + /* * If match_beginning or match_end is specified, there is no * point starting from a wrong line that will never match and diff --git a/git-add--interactive.perl b/git-add--interactive.perl index 52659bb74c..10fd30ae16 100755 --- a/git-add--interactive.perl +++ b/git-add--interactive.perl @@ -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 @@ sub list_untracked { 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; } @@ -1127,7 +1129,7 @@ sub edit_hunk_manually { 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) { diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index d4f9386621..5db6432e33 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -23,6 +23,17 @@ diff_cmp () { test_cmp "$1.filtered" "$2.filtered" } +# This function uses a trick to manipulate the interactive add to use color: +# the `want_color()` function special-cases the situation where a pager was +# spawned and Git now wants to output colored text: to detect that situation, +# the environment variable `GIT_PAGER_IN_USE` is set. However, color is +# suppressed despite that environment variable if the `TERM` variable +# indicates a dumb terminal, so we set that variable, too. + +force_color () { + env GIT_PAGER_IN_USE=true TERM=vt100 "$@" +} + test_expect_success 'setup (initial)' ' echo content >file && git add file && @@ -94,7 +105,6 @@ test_expect_success 'revert works (commit)' ' grep "unchanged *+3/-0 file" output ' - test_expect_success 'setup expected' ' cat >expected <<-\EOF EOF @@ -263,6 +273,35 @@ test_expect_success FILEMODE 'stage mode and hunk' ' # end of tests disabled when filemode is not usable +test_expect_success 'different prompts for mode change/deleted' ' + git reset --hard && + >file && + >deleted && + git add --chmod=+x file deleted && + echo changed >file && + rm deleted && + test_write_lines n n n | + git -c core.filemode=true add -p >actual && + sed -n "s/^\(([0-9/]*) Stage .*?\).*/\1/p" actual >actual.filtered && + cat >expect <<-\EOF && + (1/1) Stage deletion [y,n,q,a,d,?]? + (1/2) Stage mode change [y,n,q,a,d,j,J,g,/,?]? + (2/2) Stage this hunk [y,n,q,a,d,K,g,/,e,?]? + EOF + test_cmp expect actual.filtered +' + +test_expect_success 'correct message when there is nothing to do' ' + git reset --hard && + git add -p 2>err && + test_i18ngrep "No changes" err && + printf "\\0123" >binary && + git add binary && + printf "\\0abc" >binary && + git add -p 2>err && + test_i18ngrep "Only binary files changed" err +' + test_expect_success 'setup again' ' git reset --hard && test_chmod +x file && @@ -403,6 +442,28 @@ test_expect_failure 'split hunk "add -p (no, yes, edit)"' ' ! grep "^+31" actual ' +test_expect_failure 'edit, adding lines to the first hunk' ' + test_write_lines 10 11 20 30 40 50 51 60 >test && + git reset && + tr _ " " >patch <<-EOF && + @@ -1,5 +1,6 @@ + _10 + +11 + +12 + _20 + +21 + +22 + _30 + EOF + # test sequence is s(plit), e(dit), n(o) + # q n q q is there to make sure we exit at the end. + printf "%s\n" s e n q n q q | + EDITOR=./fake_editor.sh git add -p 2>error && + test_must_be_empty error && + git diff --cached >actual && + grep "^+22" actual +' + test_expect_success 'patch mode ignores unmerged entries' ' git reset --hard && test_commit conflict && @@ -429,35 +490,48 @@ test_expect_success 'patch mode ignores unmerged entries' ' diff_cmp expected diff ' -test_expect_success TTY 'diffs can be colorized' ' +test_expect_success 'diffs can be colorized' ' git reset --hard && echo content >test && - printf y | test_terminal git add -p >output 2>&1 && + printf y >y && + force_color git add -p >output 2>&1 test && test_config interactive.diffFilter "sed s/^/foo:/" && - printf y | test_terminal git add -p >output 2>&1 && + printf y >y && + force_color git add -p >output 2>&1 test && test_config interactive.diffFilter "echo too-short" && - printf y | test_must_fail test_terminal git add -p + printf y >y && + test_must_fail force_color git add -p file && + git add file && + echo changed >file && + test_must_fail git -c diff.algorithm=bogus add -p 2>err && + test_i18ngrep "error: option diff-algorithm accepts " err ' test_expect_success 'patch-mode via -i prompts for files' ' @@ -667,7 +741,7 @@ test_expect_success 'show help from add--helper' ' What now>$SP Bye. EOF - test_write_lines h | GIT_PAGER_IN_USE=true TERM=vt100 git add -i >actual.colored && + test_write_lines h | force_color git add -i >actual.colored && test_decode_color actual && test_i18ncmp expect actual '