Merge branch 'bl/gitweb-project-filter'
[gitweb.git] / t / t4014-format-patch.sh
index f87434b9f8e0d520813389e6ea7c94f74222767b..67975129bc3703e16fe52eb916c2e08b7908ff87 100755 (executable)
@@ -6,30 +6,36 @@
 test_description='various format-patch tests'
 
 . ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-terminal.sh
 
 test_expect_success setup '
 
        for i in 1 2 3 4 5 6 7 8 9 10; do echo "$i"; done >file &&
        cat file >elif &&
        git add file elif &&
+       test_tick &&
        git commit -m Initial &&
        git checkout -b side &&
 
        for i in 1 2 5 6 A B C 7 8 9 10; do echo "$i"; done >file &&
        test_chmod +x elif &&
+       test_tick &&
        git commit -m "Side changes #1" &&
 
        for i in D E F; do echo "$i"; done >>file &&
        git update-index file &&
+       test_tick &&
        git commit -m "Side changes #2" &&
        git tag C2 &&
 
        for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >file &&
        git update-index file &&
+       test_tick &&
        git commit -m "Side changes #3 with \\n backslash-n in it." &&
 
        git checkout master &&
        git diff-tree -p C2 | git apply --index &&
+       test_tick &&
        git commit -m "Master accepts moral equivalent of #2"
 
 '
@@ -51,6 +57,22 @@ test_expect_success "format-patch --ignore-if-in-upstream" '
 
 '
 
+test_expect_success "format-patch doesn't consider merge commits" '
+
+       git checkout -b slave master &&
+       echo "Another line" >>file &&
+       test_tick &&
+       git commit -am "Slave change #1" &&
+       echo "Yet another line" >>file &&
+       test_tick &&
+       git commit -am "Slave change #2" &&
+       git checkout -b merger master &&
+       test_tick &&
+       git merge --no-ff slave &&
+       cnt=`git format-patch -3 --stdout | grep "^From " | wc -l` &&
+       test $cnt = 3
+'
+
 test_expect_success "format-patch result applies" '
 
        git checkout -b rebuild-0 master &&
@@ -157,12 +179,21 @@ test_expect_success 'configuration To: header' '
        grep "^To: R. E. Cipient <rcipient@example.com>\$" patch9
 '
 
+# check_patch <patch>: Verify that <patch> looks like a half-sane
+# patch email to avoid a false positive with !grep
+check_patch () {
+       grep -e "^From:" "$1" &&
+       grep -e "^Date:" "$1" &&
+       grep -e "^Subject:" "$1"
+}
+
 test_expect_success '--no-to overrides config.to' '
 
        git config --replace-all format.to \
                "R. E. Cipient <rcipient@example.com>" &&
        git format-patch --no-to --stdout master..side |
        sed -e "/^\$/q" >patch10 &&
+       check_patch patch10 &&
        ! grep "^To: R. E. Cipient <rcipient@example.com>\$" patch10
 '
 
@@ -173,6 +204,7 @@ test_expect_success '--no-to and --to replaces config.to' '
        git format-patch --no-to --to="Someone Else <else@out.there>" \
                --stdout master..side |
        sed -e "/^\$/q" >patch11 &&
+       check_patch patch11 &&
        ! grep "^To: Someone <someone@out.there>\$" patch11 &&
        grep "^To: Someone Else <else@out.there>\$" patch11
 '
@@ -183,15 +215,17 @@ test_expect_success '--no-cc overrides config.cc' '
                "C. E. Cipient <rcipient@example.com>" &&
        git format-patch --no-cc --stdout master..side |
        sed -e "/^\$/q" >patch12 &&
+       check_patch patch12 &&
        ! grep "^Cc: C. E. Cipient <rcipient@example.com>\$" patch12
 '
 
-test_expect_success '--no-add-headers overrides config.headers' '
+test_expect_success '--no-add-header overrides config.headers' '
 
        git config --replace-all format.headers \
                "Header1: B. E. Cipient <rcipient@example.com>" &&
-       git format-patch --no-add-headers --stdout master..side |
+       git format-patch --no-add-header --stdout master..side |
        sed -e "/^\$/q" >patch13 &&
+       check_patch patch13 &&
        ! grep "^Header1: B. E. Cipient <rcipient@example.com>\$" patch13
 '
 
@@ -423,22 +457,22 @@ test_expect_success 'thread deep cover-letter in-reply-to' '
 '
 
 test_expect_success 'thread via config' '
-       git config format.thread true &&
+       test_config format.thread true &&
        check_threading expect.thread master
 '
 
 test_expect_success 'thread deep via config' '
-       git config format.thread deep &&
+       test_config format.thread deep &&
        check_threading expect.deep master
 '
 
 test_expect_success 'thread config + override' '
-       git config format.thread deep &&
+       test_config format.thread deep &&
        check_threading expect.thread --thread master
 '
 
 test_expect_success 'thread config + --no-thread' '
-       git config format.thread deep &&
+       test_config format.thread deep &&
        check_threading expect.no-threading --no-thread master
 '
 
@@ -458,6 +492,7 @@ test_expect_success 'cover-letter inherits diff options' '
        git mv file foo &&
        git commit -m foo &&
        git format-patch --cover-letter -1 &&
+       check_patch 0000-cover-letter.patch &&
        ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch &&
        git format-patch --cover-letter -1 -M &&
        grep "file => foo .* 0 *\$" 0000-cover-letter.patch
@@ -594,11 +629,11 @@ echo "fatal: --check does not make sense" > expect.check
 
 test_expect_success 'options no longer allowed for format-patch' '
        test_must_fail git format-patch --name-only 2> output &&
-       test_cmp expect.name-only output &&
+       test_i18ncmp expect.name-only output &&
        test_must_fail git format-patch --name-status 2> output &&
-       test_cmp expect.name-status output &&
+       test_i18ncmp expect.name-status output &&
        test_must_fail git format-patch --check 2> output &&
-       test_cmp expect.check output'
+       test_i18ncmp expect.check output'
 
 test_expect_success 'format-patch --numstat should produce a patch' '
        git format-patch --numstat --stdout master..side > output &&
@@ -635,6 +670,7 @@ test_expect_success 'format-patch --no-signature ignores format.signature' '
        git config format.signature "config sig" &&
        git format-patch --stdout --signature="my sig" --no-signature \
                -1 >output &&
+       check_patch output &&
        ! grep "config sig" output &&
        ! grep "my sig" output &&
        ! grep "^-- \$" output
@@ -651,18 +687,211 @@ test_expect_success 'format-patch --signature --cover-letter' '
 test_expect_success 'format.signature="" supresses signatures' '
        git config format.signature "" &&
        git format-patch --stdout -1 >output &&
+       check_patch output &&
        ! grep "^-- \$" output
 '
 
 test_expect_success 'format-patch --no-signature supresses signatures' '
        git config --unset-all format.signature &&
        git format-patch --stdout --no-signature -1 >output &&
+       check_patch output &&
        ! grep "^-- \$" output
 '
 
 test_expect_success 'format-patch --signature="" supresses signatures' '
-       git format-patch --signature="" -1 >output &&
+       git format-patch --stdout --signature="" -1 >output &&
+       check_patch output &&
        ! grep "^-- \$" output
 '
 
+test_expect_success TTY 'format-patch --stdout paginates' '
+       rm -f pager_used &&
+       (
+               GIT_PAGER="wc >pager_used" &&
+               export GIT_PAGER &&
+               test_terminal git format-patch --stdout --all
+       ) &&
+       test_path_is_file pager_used
+'
+
+ test_expect_success TTY 'format-patch --stdout pagination can be disabled' '
+       rm -f pager_used &&
+       (
+               GIT_PAGER="wc >pager_used" &&
+               export GIT_PAGER &&
+               test_terminal git --no-pager format-patch --stdout --all &&
+               test_terminal git -c "pager.format-patch=false" format-patch --stdout --all
+       ) &&
+       test_path_is_missing pager_used &&
+       test_path_is_missing .git/pager_used
+'
+
+test_expect_success 'format-patch handles multi-line subjects' '
+       rm -rf patches/ &&
+       echo content >>file &&
+       for i in one two three; do echo $i; done >msg &&
+       git add file &&
+       git commit -F msg &&
+       git format-patch -o patches -1 &&
+       grep ^Subject: patches/0001-one.patch >actual &&
+       echo "Subject: [PATCH] one two three" >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success 'format-patch handles multi-line encoded subjects' '
+       rm -rf patches/ &&
+       echo content >>file &&
+       for i in en två tre; do echo $i; done >msg &&
+       git add file &&
+       git commit -F msg &&
+       git format-patch -o patches -1 &&
+       grep ^Subject: patches/0001-en.patch >actual &&
+       echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
+       test_cmp expect actual
+'
+
+M8="foo bar "
+M64=$M8$M8$M8$M8$M8$M8$M8$M8
+M512=$M64$M64$M64$M64$M64$M64$M64$M64
+cat >expect <<'EOF'
+Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
+ bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
+ foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
+ bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
+ foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
+ bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
+ foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
+ bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
+ foo bar foo bar foo bar foo bar
+EOF
+test_expect_success 'format-patch wraps extremely long headers (ascii)' '
+       echo content >>file &&
+       git add file &&
+       git commit -m "$M512" &&
+       git format-patch --stdout -1 >patch &&
+       sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
+       test_cmp expect subject
+'
+
+M8="föö bar "
+M64=$M8$M8$M8$M8$M8$M8$M8$M8
+M512=$M64$M64$M64$M64$M64$M64$M64$M64
+cat >expect <<'EOF'
+Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
+EOF
+test_expect_success 'format-patch wraps extremely long headers (rfc2047)' '
+       rm -rf patches/ &&
+       echo content >>file &&
+       git add file &&
+       git commit -m "$M512" &&
+       git format-patch --stdout -1 >patch &&
+       sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
+       test_cmp expect subject
+'
+
+M8="foo_bar_"
+M64=$M8$M8$M8$M8$M8$M8$M8$M8
+cat >expect <<EOF
+From: $M64
+ <foobar@foo.bar>
+EOF
+test_expect_success 'format-patch wraps non-quotable headers' '
+       rm -rf patches/ &&
+       echo content >>file &&
+       git add file &&
+       git commit -mfoo --author "$M64 <foobar@foo.bar>" &&
+       git format-patch --stdout -1 >patch &&
+       sed -n "/^From: /p; /^ /p; /^$/q" <patch >from &&
+       test_cmp expect from
+'
+
+check_author() {
+       echo content >>file &&
+       git add file &&
+       GIT_AUTHOR_NAME=$1 git commit -m author-check &&
+       git format-patch --stdout -1 >patch &&
+       grep ^From: patch >actual &&
+       test_cmp expect actual
+}
+
+cat >expect <<'EOF'
+From: "Foo B. Bar" <author@example.com>
+EOF
+test_expect_success 'format-patch quotes dot in headers' '
+       check_author "Foo B. Bar"
+'
+
+cat >expect <<'EOF'
+From: "Foo \"The Baz\" Bar" <author@example.com>
+EOF
+test_expect_success 'format-patch quotes double-quote in headers' '
+       check_author "Foo \"The Baz\" Bar"
+'
+
+cat >expect <<'EOF'
+From: =?UTF-8?q?"F=C3=B6o=20B.=20Bar"?= <author@example.com>
+EOF
+test_expect_success 'rfc2047-encoded headers also double-quote 822 specials' '
+       check_author "Föo B. Bar"
+'
+
+cat >expect <<'EOF'
+Subject: header with . in it
+EOF
+test_expect_success 'subject lines do not have 822 atom-quoting' '
+       echo content >>file &&
+       git add file &&
+       git commit -m "header with . in it" &&
+       git format-patch -k -1 --stdout >patch &&
+       grep ^Subject: patch >actual &&
+       test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+Subject: [PREFIX 1/1] header with . in it
+EOF
+test_expect_success 'subject prefixes have space prepended' '
+       git format-patch -n -1 --stdout --subject-prefix=PREFIX >patch &&
+       grep ^Subject: patch >actual &&
+       test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+Subject: [1/1] header with . in it
+EOF
+test_expect_success 'empty subject prefix does not have extra space' '
+       git format-patch -n -1 --stdout --subject-prefix= >patch &&
+       grep ^Subject: patch >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'format patch ignores color.ui' '
+       test_unconfig color.ui &&
+       git format-patch --stdout -1 >expect &&
+       test_config color.ui always &&
+       git format-patch --stdout -1 >actual &&
+       test_cmp expect actual
+'
+
 test_done