Skip to content

Commit 15f3dba

Browse files
committed
Merge branch 'add-i-fixes'
While re-implementing `git add -i` and `git add -p` in C, I tried to make sure that there is test coverage for all of the features I convert from Perl to C, to give me some confidence in the correctness from running the test suite both with `GIT_TEST_ADD_I_USE_BUILTIN=true` and with `GIT_TEST_ADD_I_USE_BUILTIN=false`. However, I discovered that there are a couple of gaps. This patch series intends to close them. The first patch might actually not be considered a gap by some: it basically removes the need for the `TTY` prerequisite in the `git add -i` tests to verify that the output is colored all right. This change is rather crucial for me, though: on Windows, where the conversion to a built-in shows the most obvious benefits, there are no pseudo terminals (yet), therefore `git.exe` cannot work with them (even if the MSYS2 Perl interpreter used by Git for Windows knows about some sort of pty emulation). And I *really* wanted to make sure that the colors work on Windows, as I personally get a lot out of those color cues. The patch series ends by addressing two issues that are not exactly covering testing gaps: - While adding a test case, I noticed that `git add -p` exited with *success* when it could not even generate a diff. This is so obviously wrong that I had to fix it right away (I noticed, actually, because my in-progress built-in `git add -p` failed, and the Perl version did not), and I used the same test case to verify that this is fixed once and for all. - While working on covering those test gaps, I noticed a problem in an early version of the built-in version of `git add -p` where the `git apply --allow-overlap` mode failed to work properly, for little reason, and I fixed it real quick. It would seem that the `--allow-overlap` function is not only purposefully under-documented, but also purposefully under-tested, probably to discourage its use. I do not quite understand what I perceive to be Junio's aversion to that option, but I did not feel like I should put up a battle here, so I did not accompany this fix with a new test script. In the end, the built-in version of `git add -p` does not use the `--allow-overlap` function at all, anyway. Which should make everybody a lot happier. Signed-off-by: Johannes Schindelin <[email protected]>
2 parents 5f0f8fd + cb1a9e2 commit 15f3dba

File tree

3 files changed

+94
-11
lines changed

3 files changed

+94
-11
lines changed

apply.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2676,6 +2676,16 @@ static int find_pos(struct apply_state *state,
26762676
unsigned long backwards, forwards, current;
26772677
int backwards_lno, forwards_lno, current_lno;
26782678

2679+
/*
2680+
* When running with --allow-overlap, it is possible that a hunk is
2681+
* seen that pretends to start at the beginning (but no longer does),
2682+
* and that *still* needs to match the end. So trust `match_end` more
2683+
* than `match_beginning`.
2684+
*/
2685+
if (state->allow_overlap && match_beginning && match_end &&
2686+
img->nr - preimage->nr != 0)
2687+
match_beginning = 0;
2688+
26792689
/*
26802690
* If match_beginning or match_end is specified, there is no
26812691
* point starting from a wrong line that will never match and

git-add--interactive.perl

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,9 @@ sub run_cmd_pipe {
163163
} else {
164164
my $fh = undef;
165165
open($fh, '-|', @_) or die;
166-
return <$fh>;
166+
my @out = <$fh>;
167+
close $fh || die "Cannot close @_ ($!)";
168+
return @out;
167169
}
168170
}
169171

@@ -210,7 +212,7 @@ sub list_untracked {
210212
sub get_empty_tree {
211213
return $empty_tree if defined $empty_tree;
212214

213-
$empty_tree = run_cmd_pipe(qw(git hash-object -t tree /dev/null));
215+
($empty_tree) = run_cmd_pipe(qw(git hash-object -t tree /dev/null));
214216
chomp $empty_tree;
215217
return $empty_tree;
216218
}
@@ -1103,7 +1105,7 @@ sub edit_hunk_manually {
11031105
EOF2
11041106
close $fh;
11051107

1106-
chomp(my $editor = run_cmd_pipe(qw(git var GIT_EDITOR)));
1108+
chomp(my ($editor) = run_cmd_pipe(qw(git var GIT_EDITOR)));
11071109
system('sh', '-c', $editor.' "$@"', $editor, $hunkfile);
11081110

11091111
if ($? != 0) {

t/t3701-add-interactive.sh

Lines changed: 79 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,17 @@ diff_cmp () {
2323
test_cmp "$1.filtered" "$2.filtered"
2424
}
2525

26+
# This function uses a trick to manipulate the interactive add to use color:
27+
# the `want_color()` function special-cases the situation where a pager was
28+
# spawned and Git now wants to output colored text: to detect that situation,
29+
# the environment variable `GIT_PAGER_IN_USE` is set. However, color is
30+
# suppressed despite that environment variable if the `TERM` variable
31+
# indicates a dumb terminal, so we set that variable, too.
32+
33+
force_color () {
34+
env GIT_PAGER_IN_USE=true TERM=vt100 "$@"
35+
}
36+
2637
test_expect_success 'setup (initial)' '
2738
echo content >file &&
2839
git add file &&
@@ -94,7 +105,6 @@ test_expect_success 'revert works (commit)' '
94105
grep "unchanged *+3/-0 file" output
95106
'
96107

97-
98108
test_expect_success 'setup expected' '
99109
cat >expected <<-\EOF
100110
EOF
@@ -263,6 +273,35 @@ test_expect_success FILEMODE 'stage mode and hunk' '
263273

264274
# end of tests disabled when filemode is not usable
265275

276+
test_expect_success 'different prompts for mode change/deleted' '
277+
git reset --hard &&
278+
>file &&
279+
>deleted &&
280+
git add --chmod=+x file deleted &&
281+
echo changed >file &&
282+
rm deleted &&
283+
test_write_lines n n n |
284+
git -c core.filemode=true add -p >actual &&
285+
sed -n "s/^\(Stage .*?\).*/\1/p" actual >actual.filtered &&
286+
cat >expect <<-\EOF &&
287+
Stage deletion [y,n,q,a,d,?]?
288+
Stage mode change [y,n,q,a,d,j,J,g,/,?]?
289+
Stage this hunk [y,n,q,a,d,K,g,/,e,?]?
290+
EOF
291+
test_cmp expect actual.filtered
292+
'
293+
294+
test_expect_success 'correct message when there is nothing to do' '
295+
git reset --hard &&
296+
git add -p 2>err &&
297+
test_i18ngrep "No changes" err &&
298+
printf "\\0123" >binary &&
299+
git add binary &&
300+
printf "\\0abc" >binary &&
301+
git add -p 2>err &&
302+
test_i18ngrep "Only binary files changed" err
303+
'
304+
266305
test_expect_success 'setup again' '
267306
git reset --hard &&
268307
test_chmod +x file &&
@@ -403,6 +442,28 @@ test_expect_failure 'split hunk "add -p (no, yes, edit)"' '
403442
! grep "^+31" actual
404443
'
405444

445+
test_expect_failure 'edit, adding lines to the first hunk' '
446+
test_write_lines 10 11 20 30 40 50 51 60 >test &&
447+
git reset &&
448+
tr _ " " >patch <<-EOF &&
449+
@@ -1,5 +1,6 @@
450+
_10
451+
+11
452+
+12
453+
_20
454+
+21
455+
+22
456+
_30
457+
EOF
458+
# test sequence is s(plit), e(dit), n(o)
459+
# q n q q is there to make sure we exit at the end.
460+
printf "%s\n" s e n q n q q |
461+
EDITOR=./fake_editor.sh git add -p 2>error &&
462+
test_must_be_empty error &&
463+
git diff --cached >actual &&
464+
grep "^+22" actual
465+
'
466+
406467
test_expect_success 'patch mode ignores unmerged entries' '
407468
git reset --hard &&
408469
test_commit conflict &&
@@ -429,35 +490,45 @@ test_expect_success 'patch mode ignores unmerged entries' '
429490
diff_cmp expected diff
430491
'
431492

432-
test_expect_success TTY 'diffs can be colorized' '
493+
test_expect_success 'diffs can be colorized' '
433494
git reset --hard &&
434495
435496
echo content >test &&
436-
printf y | test_terminal git add -p >output 2>&1 &&
497+
printf y | force_color git add -p >output 2>&1 &&
437498
438499
# We do not want to depend on the exact coloring scheme
439500
# git uses for diffs, so just check that we saw some kind of color.
440501
grep "$(printf "\\033")" output
441502
'
442503

443-
test_expect_success TTY 'diffFilter filters diff' '
504+
test_expect_success 'diffFilter filters diff' '
444505
git reset --hard &&
445506
446507
echo content >test &&
447508
test_config interactive.diffFilter "sed s/^/foo:/" &&
448-
printf y | test_terminal git add -p >output 2>&1 &&
509+
printf y | force_color git add -p >output 2>&1 &&
449510
450511
# avoid depending on the exact coloring or content of the prompts,
451512
# and just make sure we saw our diff prefixed
452513
grep foo:.*content output
453514
'
454515

455-
test_expect_success TTY 'detect bogus diffFilter output' '
516+
test_expect_success 'detect bogus diffFilter output' '
456517
git reset --hard &&
457518
458519
echo content >test &&
459520
test_config interactive.diffFilter "echo too-short" &&
460-
printf y | test_must_fail test_terminal git add -p
521+
printf y | test_must_fail force_color git add -p
522+
'
523+
524+
test_expect_success 'diff.algorithm is passed to `git diff-files`' '
525+
git reset --hard &&
526+
527+
>file &&
528+
git add file &&
529+
echo changed >file &&
530+
test_must_fail git -c diff.algorithm=bogus add -p 2>err &&
531+
test_i18ngrep "error: option diff-algorithm accepts " err
461532
'
462533

463534
test_expect_success 'patch-mode via -i prompts for files' '
@@ -658,7 +729,7 @@ test_expect_success 'show help from add--helper' '
658729
<BOLD;BLUE>What now<RESET>>$SP
659730
Bye.
660731
EOF
661-
test_write_lines h | GIT_PAGER_IN_USE=true TERM=vt100 git add -i >actual.colored &&
732+
test_write_lines h | force_color git add -i >actual.colored &&
662733
test_decode_color <actual.colored >actual &&
663734
test_i18ncmp expect actual
664735
'

0 commit comments

Comments
 (0)