From 69b3e726a354901af2502438d271fd4509ad83ac Mon Sep 17 00:00:00 2001 From: Bryce Kwon Date: Sat, 7 Nov 2026 13:23:33 -1000 Subject: Compare more of the patch page with git The root patch was checked for its signature alone, so one that lost its diff passed. The headers, the note a path adds to the stat and a merge in a range had no test, and a renamed file's patch was grepped rather than compared. The version is read in the test that needs it, so a missing build/VERSION fails there instead of surfacing later as a mismatch. --- tests/t0109-patch.sh | 115 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 82 insertions(+), 33 deletions(-) (limited to 'tests/t0109-patch.sh') diff --git a/tests/t0109-patch.sh b/tests/t0109-patch.sh index f87f145..9077960 100755 --- a/tests/t0109-patch.sh +++ b/tests/t0109-patch.sh @@ -1,56 +1,59 @@ #!/bin/sh # The patch page serves mail ready patches, compared line for line against -# git format-patch for a single commit and for a range, once the CGI headers -# are stripped. +# git format-patch for a single commit, the root commit, a range and a +# renamed file, once the CGI headers are stripped. Further checks cover the +# headers, max-patch-count, a path, a merge in a range, the signature and the +# format used when addresses are hidden. test_description='Check content on patch page' . ./setup.sh -# The version the built binary signs its patches with, without the v of the -# tag, as git writes its own. -CGIT_VERSION=$(sed -n "s/CGIT_VERSION = v\{0,1\}//p" "$TEST_OUTPUT_DIRECTORY/../build/VERSION") - # The signature sits on the second-to-last line, above the trailing blank, # and names the version only when enable-version-info asks for it. check_cgit_signature() { - tail -2 tmp | head -1 | grep -x -F "cgit${1:+ $1}" + tail -n 2 tmp | head -n 1 | grep -x -F "cgit${1:+ $1}" } -test_expect_success 'generate foo/patch' ' - cgit_url "foo/patch" >tmp -' - -test_expect_success 'compare with output of git-format-patch(1)' ' +test_expect_success 'a commit is patched as git format-patch writes it' ' + cgit_ok_url "foo/patch" >tmp && git -C repos/foo format-patch --subject-prefix="" \ --signature="cgit" --stdout HEAD^ >expect && strip_headers actual && test_cmp expect actual ' -test_expect_success 'find initial commit' ' - root=$(git -C repos/foo rev-list --max-parents=0 HEAD) -' - -test_expect_success 'generate patch for initial commit' ' - cgit_url "foo/patch&id=$root" >tmp +# A commit is named as the range from its parent, which the root commit lacks. +test_expect_success 'the patch is plain text named after the commit' ' + id=$(git -C repos/foo rev-parse HEAD) && + parent=$(git -C repos/foo rev-parse HEAD~1) && + cgit_ok_url "foo/patch" >tmp && + sed "/^$/q" tmp >headers && + grep "^Content-Type: text/plain" headers && + grep "^Content-Disposition: inline; filename=\"$parent..$id.patch\"$" headers ' -test_expect_success 'find `cgit` signature on the initial commit' ' - check_cgit_signature +test_expect_success 'the root commit is patched whole' ' + root=$(git -C repos/foo rev-list --max-parents=0 HEAD) && + cgit_ok_url "foo/patch&id=$root" >tmp && + git -C repos/foo format-patch --root -1 --subject-prefix="" \ + --signature="cgit" --stdout "$root" >expect && + strip_headers actual && + test_cmp expect actual && + sed "/^$/q" tmp >headers && + grep "^Content-Disposition: inline; filename=\"$root.patch\"$" headers ' -test_expect_success 'generate patches for multiple commits' ' +test_expect_success 'a range matches git format-patch and names the range' ' id=$(git -C repos/foo rev-parse HEAD) && id2=$(git -C repos/foo rev-parse HEAD~3) && - cgit_url "foo/patch&id=$id&id2=$id2" >tmp -' - -test_expect_success 'compare the range with git-format-patch(1)' ' + cgit_ok_url "foo/patch&id=$id&id2=$id2" >tmp && git -C repos/foo format-patch --subject-prefix="" \ -N --signature="cgit" --stdout HEAD~3..HEAD >expect && strip_headers actual && - test_cmp expect actual + test_cmp expect actual && + sed "/^$/q" tmp >headers && + grep "^Content-Disposition: inline; filename=\"$id2..$id.patch\"$" headers ' # git cuts the walk short before it reverses it, so the newest commits are @@ -76,10 +79,51 @@ test_expect_success 'max-patch-count defaults to 50 and 0 lifts it' ' test $(grep -c "^From [0-9a-f]* Mon Sep 17 00:00:00 2001$" tmp) -eq 51 ' +test_expect_success 'a path limits a range to the commits touching it' ' + id2=$(git -C repos/foo rev-parse HEAD~3) && + cgit_ok_url "foo/patch/file-4&id2=$id2" >tmp && + grep "^Subject: " tmp >actual && + test_write_lines "Subject: commit 4" >expect && + test_cmp expect actual && + grep "^(limited to .file-4.)$" tmp && + ! grep "file-5" tmp +' + +# A merge has no single patch to give, so it drops out of a range, signature +# and all, while the commits it brought in stay. +test_expect_success 'a merge drops out of a range' ' + mkrepo repos/merged 1 && + ( + cd repos/merged && + git checkout -b side && + echo side >side.txt && + git add side.txt && + git commit -m side && + git checkout - && + echo main >main.txt && + git add main.txt && + git commit -m main && + git merge --no-ff -m merge side + ) && + root=$(git -C repos/merged rev-list --max-parents=0 HEAD) && + cgitrc_repo mergedrc merged && + cgit_ok mergedrc "url=merged/patch&id2=$root" >tmp && + git -C repos/merged format-patch --subject-prefix="" \ + -N --signature="cgit" --stdout "$root..HEAD" >expect && + strip_headers actual && + test_cmp expect actual && + grep "^Subject: side$" actual && + grep "^Subject: main$" actual +' + +# The version comes from the build, less the v of the tag, as git writes its +# own. test_expect_success 'the signature names the version when asked to' ' + version=$(sed -n "s/^CGIT_VERSION = v\{0,1\}//p" "$TEST_OUTPUT_DIRECTORY/../build/VERSION") && + test -n "$version" && cgitrc_copy versionrc enable-version-info=1 && - cgit_rc versionrc "url=foo/patch" >tmp && - check_cgit_signature "$CGIT_VERSION" + cgit_ok versionrc "url=foo/patch" >tmp && + check_cgit_signature "$version" ' # Without plain email the patch is written from a format of cgit's own, whose @@ -93,7 +137,8 @@ test_expect_success 'enable-plain-email=0 leaves the address off the patch' ' ' # The old name of a file renamed in the commit joins the limit, so the patch -# carries the rename rather than a file added whole. +# carries the rename rather than a file added whole. It matches git given both +# names, but for the note naming the limit. test_expect_success 'a renamed file is patched as the rename' ' mkrepo repos/moved 1 && ( @@ -105,10 +150,14 @@ test_expect_success 'a renamed file is patched as the rename' ' git commit -m "rename old.txt" ) && cgitrc_repo movedrc moved && - cgit_rc movedrc "url=moved/patch/new.txt" >tmp && - grep "^rename from old.txt$" tmp && - grep "^rename to new.txt$" tmp && - ! grep "^new file mode" tmp + cgit_ok movedrc "url=moved/patch/new.txt" >tmp && + git -C repos/moved format-patch -1 -M --subject-prefix="" \ + --signature="cgit" --stdout HEAD -- new.txt old.txt >expect && + strip_headers body && + sed "/^(limited to .new.txt.)$/,/^$/d" body >actual && + test_cmp expect actual && + grep "^similarity index 100%$" actual && + grep "^rename from old.txt$" actual ' test_done -- cgit 2.12.1