1#!/bin/sh
   2test_description='diff function context'
   4. ./test-lib.sh
   6dir="$TEST_DIRECTORY/t4051"
   8commit_and_tag () {
  10        tag=$1 &&
  11        shift &&
  12        git add "$@" &&
  13        test_tick &&
  14        git commit -m "$tag" &&
  15        git tag "$tag"
  16}
  17first_context_line () {
  19        awk '
  20                found {print; exit}
  21                /^@@/ {found = 1}
  22        '
  23}
  24last_context_line () {
  26        sed -ne \$p
  27}
  28check_diff () {
  30        name=$1
  31        desc=$2
  32        options="-W $3"
  33        test_expect_success "$desc" '
  35                git diff $options "$name^" "$name" >"$name.diff"
  36        '
  37        test_expect_success ' diff applies' '
  39                test_when_finished "git reset --hard" &&
  40                git checkout --detach "$name^" &&
  41                git apply --index "$name.diff" &&
  42                git diff --exit-code "$name"
  43        '
  44}
  45test_expect_success 'setup' '
  47        cat "$dir/includes.c" "$dir/dummy.c" "$dir/dummy.c" "$dir/hello.c" \
  48                "$dir/dummy.c" "$dir/dummy.c" >file.c &&
  49        commit_and_tag initial file.c &&
  50        grep -v "delete me from hello" <file.c >file.c.new &&
  52        mv file.c.new file.c &&
  53        commit_and_tag changed_hello file.c &&
  54        grep -v "delete me from includes" <file.c >file.c.new &&
  56        mv file.c.new file.c &&
  57        commit_and_tag changed_includes file.c &&
  58        cat "$dir/appended1.c" >>file.c &&
  60        commit_and_tag appended file.c &&
  61        cat "$dir/appended2.c" >>file.c &&
  63        commit_and_tag extended file.c &&
  64        grep -v "Begin of second part" <file.c >file.c.new &&
  66        mv file.c.new file.c &&
  67        commit_and_tag long_common_tail file.c &&
  68        git checkout initial &&
  70        cat "$dir/hello.c" "$dir/dummy.c" >file.c &&
  71        commit_and_tag hello_dummy file.c &&
  72        # overlap function context of 1st change and -u context of 2nd change
  74        grep -v "delete me from hello" <"$dir/hello.c" >file.c &&
  75        sed "2a\\
  76             extra line" <"$dir/dummy.c" >>file.c &&
  77        commit_and_tag changed_hello_dummy file.c &&
  78        git checkout initial &&
  80        grep -v "delete me from hello" <file.c >file.c.new &&
  81        mv file.c.new file.c &&
  82        cat "$dir/appended1.c" >>file.c &&
  83        commit_and_tag changed_hello_appended file.c
  84'
  85check_diff changed_hello 'changed function'
  87test_expect_success ' context includes comment' '
  89        grep "^ .*Hello comment" changed_hello.diff
  90'
  91test_expect_success ' context includes begin' '
  93        grep "^ .*Begin of hello" changed_hello.diff
  94'
  95test_expect_success ' context includes end' '
  97        grep "^ .*End of hello" changed_hello.diff
  98'
  99test_expect_success ' context does not include other functions' '
 101        test $(grep -c "^[ +-].*Begin" changed_hello.diff) -le 1
 102'
 103test_expect_success ' context does not include preceding empty lines' '
 105        test "$(first_context_line <changed_hello.diff)" != " "
 106'
 107test_expect_success ' context does not include trailing empty lines' '
 109        test "$(last_context_line <changed_hello.diff)" != " "
 110'
 111check_diff changed_includes 'changed includes'
 113test_expect_success ' context includes begin' '
 115        grep "^ .*Begin.h" changed_includes.diff
 116'
 117test_expect_success ' context includes end' '
 119        grep "^ .*End.h" changed_includes.diff
 120'
 121test_expect_success ' context does not include other functions' '
 123        test $(grep -c "^[ +-].*Begin" changed_includes.diff) -le 1
 124'
 125test_expect_success ' context does not include trailing empty lines' '
 127        test "$(last_context_line <changed_includes.diff)" != " "
 128'
 129check_diff appended 'appended function'
 131test_expect_success ' context includes begin' '
 133        grep "^[+].*Begin of first part" appended.diff
 134'
 135test_expect_success ' context includes end' '
 137        grep "^[+].*End of first part" appended.diff
 138'
 139test_expect_success ' context does not include other functions' '
 141        test $(grep -c "^[ +-].*Begin" appended.diff) -le 1
 142'
 143check_diff extended 'appended function part'
 145test_expect_success ' context includes begin' '
 147        grep "^ .*Begin of first part" extended.diff
 148'
 149test_expect_success ' context includes end' '
 151        grep "^[+].*End of second part" extended.diff
 152'
 153test_expect_success ' context does not include other functions' '
 155        test $(grep -c "^[ +-].*Begin" extended.diff) -le 2
 156'
 157test_expect_success ' context does not include preceding empty lines' '
 159        test "$(first_context_line <extended.diff)" != " "
 160'
 161check_diff long_common_tail 'change with long common tail and no context' -U0
 163test_expect_success ' context includes begin' '
 165        grep "^ .*Begin of first part" long_common_tail.diff
 166'
 167test_expect_success ' context includes end' '
 169        grep "^ .*End of second part" long_common_tail.diff
 170'
 171test_expect_success ' context does not include other functions' '
 173        test $(grep -c "^[ +-].*Begin" long_common_tail.diff) -le 2
 174'
 175test_expect_success ' context does not include preceding empty lines' '
 177        test "$(first_context_line <long_common_tail.diff.diff)" != " "
 178'
 179check_diff changed_hello_appended 'changed function plus appended function'
 181test_expect_success ' context includes begin' '
 183        grep "^ .*Begin of hello" changed_hello_appended.diff &&
 184        grep "^[+].*Begin of first part" changed_hello_appended.diff
 185'
 186test_expect_success ' context includes end' '
 188        grep "^ .*End of hello" changed_hello_appended.diff &&
 189        grep "^[+].*End of first part" changed_hello_appended.diff
 190'
 191test_expect_success ' context does not include other functions' '
 193        test $(grep -c "^[ +-].*Begin" changed_hello_appended.diff) -le 2
 194'
 195check_diff changed_hello_dummy 'changed two consecutive functions'
 197test_expect_success ' context includes begin' '
 199        grep "^ .*Begin of hello" changed_hello_dummy.diff &&
 200        grep "^ .*Begin of dummy" changed_hello_dummy.diff
 201'
 202test_expect_success ' context includes end' '
 204        grep "^ .*End of hello" changed_hello_dummy.diff &&
 205        grep "^ .*End of dummy" changed_hello_dummy.diff
 206'
 207test_expect_success ' overlapping hunks are merged' '
 209        test $(grep -c "^@@" changed_hello_dummy.diff) -eq 1
 210'
 211test_done