#!/bin/sh # The atom page serves recent history as a feed. The checks read the content # type, the feed and entry elements, what max-atom-items and a path let in, # and the escaping XML needs, and hand each feed to xmllint where installed. test_description='Check the atom feed' . ./setup.sh test_lazy_prereq XMLLINT 'command -v xmllint' # The feed's own updated is the newest commit's, in UTC like every feed date. test_expect_success 'the response is an atom feed' ' cgit_ok_url "foo/atom" >tmp && sed "/^$/q" tmp | grep "^Content-Type: application/atom+xml" && strip_headers feed && grep "" feed && grep "foo, branch master" feed && sed -n "1,/^$/p" feed >top && grep "^2005-04-01T11:14:15Z$" top ' test_expect_success XMLLINT 'the feed is well-formed xml' ' cgit_ok_url "foo/atom" >tmp && strip_headers feed && xmllint --noout feed ' test_expect_success 'every commit of a small repository is an entry' ' cgit_ok_url "foo/atom" >tmp && test $(grep -c "" tmp) -eq 5 && grep "commit 1" tmp && grep "commit 5" tmp ' # The author and committer dates differ, so each lands in its own element, and # a second branch holds a commit only all=1 lets in. test_expect_success 'set up a repo with a commit dated twice' ' test_create_repo repos/stamped && ( cd repos/stamped && GIT_AUTHOR_DATE="@1112354055 +0200" \ GIT_COMMITTER_DATE="@1112911993 +0000" \ git commit --allow-empty -m stamped -m "the body" && git checkout -b side && git commit --allow-empty -m aside && git checkout - ) && cgitrc_repo stampedrc stamped ' test_expect_success 'an entry carries the commit it stands for' ' hex=$(git -C repos/stamped rev-parse master) && algo=$(git -C repos/stamped rev-parse --show-object-format) && cgit_ok stampedrc "url=stamped/atom" >tmp && strip_headers feed && sed -n "1,/^$/p" feed >top && grep "^2005-04-07T22:13:13Z$" top && sed -n "/^$/,/^<\/entry>$/p" feed | tr -d "\047" >actual && cat >expect <<-EOF && stamped 2005-04-07T22:13:13Z A U Thor author@example.com 2005-04-01T11:14:15Z urn:$algo:$hex the body EOF test_cmp expect actual ' test_expect_success 'all=1 follows every branch and names none' ' cgit_ok stampedrc "url=stamped/atom&all=1" >tmp && grep "stamped" tmp && grep "aside" tmp && ! grep ", branch" tmp && cgit_ok stampedrc "url=stamped/atom" >tmp && grep "stamped, branch master" tmp && ! grep "aside" tmp ' test_expect_success 'ten entries is the default ceiling' ' cgit_ok_url "bar/atom" >tmp && test $(grep -c "" tmp) -eq 10 && grep "commit 50" tmp && ! grep "commit 40" tmp ' test_expect_success 'max-atom-items overrides the ceiling' ' cgitrc_repo atomrc bar max-atom-items=3 && cgit_ok atomrc "url=bar/atom" >tmp && test $(grep -c "" tmp) -eq 3 && grep "commit 48" tmp ' test_expect_success 'max-atom-items 0 empties the feed and below 0 lets all in' ' cgitrc_repo atomrc bar max-atom-items=0 && cgit_ok atomrc "url=bar/atom" >tmp && grep "bar, branch master" tmp && grep "^1970-01-01T00:00:00Z$" tmp && ! grep "" tmp && cgitrc_repo atomrc bar max-atom-items=-1 && cgit_ok atomrc "url=bar/atom" >tmp && test $(grep -c "" tmp) -eq 50 ' # A path starting with a colon would reach git as pathspec magic, which the # log refuses as well. test_expect_success 'a path with pathspec magic is refused' ' cgit_url "foo/atom/%3A%28icase%29FILE-1" >tmp && grep "^Status: 400" tmp && cgit_ok_url "foo/atom/file-1" >tmp && test $(grep -c "" tmp) -eq 1 && grep "commit 1" tmp && grep "foo/file-1, branch master" tmp ' test_expect_success 'enable-plain-email=0 leaves the address out of the feed' ' cgitrc_copy plainrc enable-plain-email=0 && cgit_ok plainrc "url=foo/atom" >tmp && grep "A U Thor" tmp && ! grep "" tmp && ! grep "author@example.com" tmp ' test_expect_success 'the feed link encodes the repository and the branch' ' cgitrc_copy feedrc && CGIT_CONFIG="$PWD/feedrc" HTTP_HOST=example.org QUERY_STRING="url=foo%2Bbar/log/&h=1%2B2" cgit >tmp 2>err && test_must_be_empty err && grep "^Status: 200" tmp && grep "title=.Atom feed. href=.http://example.org/foo%2Bbar/atom/?h=1%2B2." tmp ' # A reader may subscribe before the first push, and the page every other view # of an empty repository falls back to is no feed it can read. Atom wants an # updated element even then, and the epoch stands in. test_expect_success 'an empty repository answers with a feed of no entries' ' git init -q --bare repos/empty.git && cgitrc_repo emptyrc empty "repo.path=$PWD/repos/empty.git" && cgit_ok emptyrc "url=empty/atom" >tmp && sed "/^$/q" tmp | grep "Content-Type: application/atom+xml" && strip_headers feed && grep "empty" feed && grep "^1970-01-01T00:00:00Z$" feed && ! grep "" feed && grep "" feed ' test_expect_success XMLLINT 'the empty feed is well-formed xml' ' cgit_ok emptyrc "url=empty/atom" >tmp && strip_headers feed && xmllint --noout feed ' # Markup in a message has to be escaped, and a control byte, a byte that is # no UTF-8 and the two noncharacters XML forbids each make a reader reject # the whole feed, so they are replaced. Valid UTF-8 is kept as it is. git # commit would rewrite the stray bytes as Latin-1, so the object is written # by hand. A commit has its stray bytes replaced as it is parsed, so the # description, which comes from the config as it was written, carries one to # the feed. test_expect_success 'set up a commit holding what XML cannot carry' ' test_create_repo repos/odd && ( cd repos/odd && tree=$(git mktree commit && printf "author Odd & Name \003 \375 \357\277\276 X 1112354055 +0200\n" >>commit && printf "committer C O Mitter 1112354055 +0200\n\n" >>commit && printf "a < b & c \001 \377 \357\277\276 \303\251\n\nbody > x & \002 \376 \357\277\277\n" >>commit && oid=$(git hash-object -t commit -w commit) && git update-ref HEAD "$oid" && git cat-file commit HEAD >actual && test_cmp commit actual ) && cgitrc_repo oddrc odd "repo.desc=$(printf "d < e & \004 \374 \357\277\277 \303\251")" ' test_expect_success 'the feed escapes markup and replaces what XML forbids' ' cgit_ok oddrc "url=odd/atom" >tmp && strip_headers oddfeed && printf "d < e & ? ? ? \303\251\n" >expect && grep "^" oddfeed >actual && test_cmp expect actual && printf "a < b & c ? ? ? \303\251\n" >expect && grep "^a " oddfeed >actual && test_cmp expect actual && printf "<content type=\047text\047>body > x & ? ? ?\n" >expect && grep "^<content " oddfeed >actual && test_cmp expect actual && printf "<name>Odd & Name ? ? ? X</name>\n" >expect && grep "^<name>" oddfeed >actual && test_cmp expect actual ' test_expect_success XMLLINT 'that feed is well-formed xml' ' cgit_ok oddrc "url=odd/atom" >tmp && strip_headers <tmp >oddfeed && xmllint --noout oddfeed ' test_done