diff --git a/combine-diff.c b/combine-diff.c index b82f46cc60..1a6f9d1df5 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -164,20 +164,22 @@ static void consume_line(void *state_, char *line, unsigned long len) &state->nb, &state->nn)) return; state->lno = state->nb; - if (!state->nb) - /* @@ -1,2 +0,0 @@ to remove the - * first two lines... - */ - state->nb = 1; - if (state->nn == 0) + if (state->nn == 0) { /* @@ -X,Y +N,0 @@ removed Y lines * that would have come *after* line N * in the result. Our lost buckets hang * to the line after the removed lines, + * + * Note that this is correct even when N == 0, + * in which case the hunk removes the first + * line in the file. */ state->lost_bucket = &state->sline[state->nb]; - else + if (!state->nb) + state->nb = 1; + } else { state->lost_bucket = &state->sline[state->nb-1]; + } if (!state->sline[state->nb-1].p_lno) state->sline[state->nb-1].p_lno = xcalloc(state->num_parent, diff --git a/t/t4038-diff-combined.sh b/t/t4038-diff-combined.sh new file mode 100755 index 0000000000..2cf7e01ac2 --- /dev/null +++ b/t/t4038-diff-combined.sh @@ -0,0 +1,84 @@ +#!/bin/sh + +test_description='combined diff' + +. ./test-lib.sh + +setup_helper () { + one=$1 branch=$2 side=$3 && + + git branch $side $branch && + for l in $one two three fyra + do + echo $l + done >file && + git add file && + test_tick && + git commit -m $branch && + git checkout $side && + for l in $one two three quatro + do + echo $l + done >file && + git add file && + test_tick && + git commit -m $side && + test_must_fail git merge $branch && + for l in $one three four + do + echo $l + done >file && + git add file && + test_tick && + git commit -m "merge $branch into $side" +} + +verify_helper () { + it=$1 && + + # Ignore lines that were removed only from the other parent + sed -e ' + 1,/^@@@/d + /^ -/d + s/^\(.\)./\1/ + ' "$it" >"$it.actual.1" && + sed -e ' + 1,/^@@@/d + /^- /d + s/^.\(.\)/\1/ + ' "$it" >"$it.actual.2" && + + git diff "$it^" "$it" -- | sed -e '1,/^@@/d' >"$it.expect.1" && + test_cmp "$it.expect.1" "$it.actual.1" && + + git diff "$it^2" "$it" -- | sed -e '1,/^@@/d' >"$it.expect.2" && + test_cmp "$it.expect.2" "$it.actual.2" +} + +test_expect_success setup ' + >file && + git add file && + test_tick && + git commit -m initial && + + git branch withone && + git branch sansone && + + git checkout withone && + setup_helper one withone sidewithone && + + git checkout sansone && + setup_helper "" sansone sidesansone +' + +test_expect_success 'check combined output (1)' ' + git show sidewithone -- >sidewithone && + verify_helper sidewithone +' + +test_expect_failure 'check combined output (2)' ' + git show sidesansone -- >sidesansone && + verify_helper sidesansone +' + +test_done