#!/bin/sh # The diff page, unified or side-by-side under dt=1. The first checks read # the markup for one added file in the fixture repository, then a path, a # range, the root commit and a commit holding every kind of change the # unified view words differently. The rest build repositories of their own, # shaped for the side-by-side renderer's line numbers and character marking, # for the options a request or the config sets, and for a renamed or # followed file. test_description='Check content on diff page' . ./setup.sh test_expect_success 'an added file shows its header, links and line' ' cgit_ok_url "foo/diff" >tmp && grep "a/file-5 b/file-5" tmp && grep "@@ -0,0 +1 @@" tmp && grep "
+5
" tmp ' # The unified diff sits in a single cell, which holds the files together # rather than tabulating them, so a screen reader is told it is layout. test_expect_success 'the unified diff table is read as layout' ' cgit_ok_url "foo/diff" >tmp && grep "" tmp ' # A revision that names no commit is quoted the way the request wrote it, as # the commit and patch pages quote it, on either side of the diff. test_expect_success 'a tree on either side is named as the request gave it' ' tree=$(git -C repos/foo rev-parse --short HEAD^{tree}) && cgit_url "foo/diff/&id=$tree" >tmp && grep "^Status: 404" tmp && grep "
Not a commit: $tree
" tmp && cgit_url "foo/diff/&id2=$tree" >tmp && grep "^Status: 404" tmp && grep "
Not a commit: $tree
" tmp ' test_expect_success 'a path limits the diff and the stat says so' ' cgit_ok_url "foo/diff/file-5" >tmp && grep "Diffstat (limited to .file-5.)" tmp && grep "diff --git a/file-5 b/file-5" tmp ' test_expect_success 'a diff between two named commits spans both' ' id=$(git -C repos/foo rev-parse HEAD) && id2=$(git -C repos/foo rev-parse HEAD~2) && cgit_ok_url "foo/diff&id=$id&id2=$id2" >tmp && grep "diff --git a/file-4 b/file-4" tmp && grep "diff --git a/file-5 b/file-5" tmp && grep "
2 files changed, 2 insertions, 0 deletions
" tmp ' test_expect_success 'the root commit is diffed against nothing' ' root=$(git -C repos/foo rev-list --max-parents=0 HEAD) && cgit_ok_url "foo/diff&id=$root" >tmp && grep "diff --git a/file-1 b/file-1
new file mode 100644" tmp && grep "
1 file changed, 1 insertion, 0 deletions
" tmp ' # One commit deletes a file, changes the mode of another, changes a binary # file and moves a submodule to another commit. The changes are staged one by # one, since commit -a would take the submodule for deleted. test_expect_success 'set up a commit of every kind of change' ' mkrepo repos/kinds 1 && ( cd repos/kinds && one=$(git rev-parse HEAD) && echo gone >gone.txt && echo mode >mode.sh && printf "\000old" >bin.dat && git add gone.txt mode.sh bin.dat && git update-index --add --cacheinfo 160000,$one,sub && git commit -m "add the files" && two=$(git rev-parse HEAD) && git rm -q gone.txt && git update-index --chmod=+x mode.sh && printf "\000new" >bin.dat && git add bin.dat && git update-index --cacheinfo 160000,$two,sub && git commit -m "change the files" ) && cgitrc_repo kindsrc kinds ' test_expect_success 'each kind of change is worded as git words it' ' one=$(git -C repos/kinds rev-parse HEAD~2) && two=$(git -C repos/kinds rev-parse HEAD~1) && cgit_ok kindsrc "url=kinds/diff/" >tmp && grep "diff --git a/gone.txt b/gone.txt
deleted file mode 100644" tmp && grep "" tmp && grep "
index [0-9a-f]*\.\.[0-9a-f]* 100644\.\.100755
" tmp && grep "" tmp && grep "Binary files differ" tmp && grep "
-Subproject $one
+Subproject $two
" tmp ' # git writes a hunk length only when the hunk spans more than one line, so the # header for a single line reads "@@ -1 +1 @@" with no comma in it. Requiring # that comma left those hunks numbered from zero, which dropped the line # number link altogether. test_expect_success 'set up a repo with single-line hunks' ' mkrepo repos/hunk1 1 && ( cd repos/hunk1 && printf "only\n" >one.txt && git add one.txt && git commit -m "add one.txt" && printf "ONLY\n" >one.txt && git commit -am "change one.txt" ) && cgitrc_repo hunk1rc hunk1 && git -C repos/hunk1 diff HEAD~1 HEAD >raw.diff && grep "^@@ -1 +1 @@" raw.diff ' test_expect_success 'ssdiff numbers a comma-less hunk from its real line' ' old=$(git -C repos/hunk1 rev-parse HEAD~1) && new=$(git -C repos/hunk1 rev-parse HEAD) && cgit_ok hunk1rc "url=hunk1/diff/&dt=1" >tmp && grep "1" tmp && grep "1" tmp ' # A line dropped near the top leaves the two sides of the later hunk starting # at different lines, so each side has to be numbered from its own half of the # header. test_expect_success 'set up a repo whose later hunk starts apart on each side' ' mkrepo repos/later 1 && ( cd repos/later && test_seq 1 20 >twenty.txt && git add twenty.txt && git commit -m "add twenty.txt" && test_seq 1 20 | sed -e 2d -e s/^15$/fifteen/ >twenty.txt && git commit -am "change twenty.txt" ) && cgitrc_repo laterrc later && git -C repos/later diff HEAD~1 HEAD >raw.diff && grep "^@@ -12,7 +11,7 @@" raw.diff ' test_expect_success 'ssdiff numbers each side of a hunk from its own start' ' old=$(git -C repos/later rev-parse HEAD~1) && new=$(git -C repos/later rev-parse HEAD) && cgit_ok laterrc "url=later/diff/&dt=1" >tmp && grep -x "" tmp && grep -x "" tmp && grep "15$" tmp) -eq 40 && test $(grep -c "^$" tmp) -eq 40 ' test_expect_success 'stripping the highlight leaves each side its own lines' ' cgit_ok lcsrc "url=lcs/diff/&dt=1" >tmp && sed -n "s/^ EOF test_cmp expect actual ' # A file added or deleted fills one side, leaving the other a darker blank, # and a changed pair with nothing in common is marked whole. Forced colours # drop the backgrounds, so those cells keep a thicker border instead. test_expect_success 'each side of a row is classed by what it holds' ' cgit_ok_url "foo/diff&dt=1" >tmp && grep -x "" tmp && grep "" tmp && cgit_ok hunk1rc "url=hunk1/diff/&dt=1" >tmp && grep "$" tmp && grep "$" tmp ' test_expect_success 'forced colours mark the changed cells with a border' ' sed -n "/^@media (forced-colors: active) {$/,/^}/p" \ "$TEST_OUTPUT_DIRECTORY/../assets/cgit.css" >rule && sed -n "/^ div#cgit table.ssdiff td.add,$/,/^ }$/p" rule >cells && grep "^ div#cgit table.ssdiff td.del,$" cells && grep "^ div#cgit table.ssdiff td.changed {$" cells && grep "^ border-left-width: 4px;$" cells ' # Removals and additions that do not pair off are shown without marking, # with a dark blank where a side runs out. A line past the comparison's # limit is shown whole, a tab is expanded, and a binary file says so. test_expect_success 'set up a commit for the remaining side-by-side rows' ' mkrepo repos/cells 1 && ( cd repos/cells && test_write_lines gone >gone.txt && test_write_lines one two keep >uneven.txt && printf "%0130d\n" 0 >long.txt && printf "a\tb\nx\n" >tab.txt && printf "\000old" >bin.dat && git add . && git commit -m "add the files" && git rm -q gone.txt && test_write_lines ONE keep >uneven.txt && printf "%0129d1\n" 0 >long.txt && printf "a\tb\ny\n" >tab.txt && printf "\000new" >bin.dat && git commit -am "change the files" ) && cgitrc_repo cellsrc cells ' test_expect_success 'the remaining side-by-side rows' ' cgit_ok cellsrc "url=cells/diff/&dt=1" >tmp && grep "$" tmp && grep -x "" tmp && grep "$" tmp && grep "$" tmp && grep "$" tmp && grep -x "" tmp && grep "$" tmp && grep "$" tmp && grep "$" tmp && grep "" tmp ' test_expect_success 'a side-by-side diff past max-diff-lines is cut short' ' cgitrc_repo cellscaprc cells max-diff-lines=1 && cgit_ok cellscaprc "url=cells/diff/&dt=1" >tmp && grep "" tmp ' # A stat limited to one file is no use, so the file links leave dt=2 behind. test_expect_success 'dt=2 shows the diffstat alone' ' cgit_ok_url "foo/diff&dt=2" >tmp && grep "" tmp && grep "
1 file changed, 1 insertion, 0 deletions
" tmp && ! grep "class=.hunk." tmp && ! grep "
-rwxr-xr-x\[-rw-r--r--\]bin4 -> 4 bytes12121112
" tmp && grep "14" tmp ' # The character level highlight reuses one table across every changed pair, so # these lines get shorter as the file goes on and each comparison is smaller # than the one before it. That is where a cell left over from the previous # pair shows itself, as a del or an add span sitting over the wrong # characters. test_expect_success 'set up a repo with shrinking changed lines' ' mkrepo repos/lcs 1 && ( cd repos/lcs && awk "BEGIN{for(n=120;n>0;n-=3){s=\"\"; for(i=0;ilines.txt && git add lines.txt && git commit -m "add lines.txt" && awk "BEGIN{for(n=120;n>0;n-=3){s=\"\"; for(i=0;ilines.txt && git commit -am "change every line" ) && cgitrc_repo lcsrc lcs ' # Each side of a row is written on a line of its own, the old side first and # the new side closing the row. test_expect_success 'every changed pair gets both a del and an add span' ' cgit_ok lcsrc "url=lcs/diff/&dt=1" >tmp && test $(grep -c "^.*.*.*.*.*.*
]*>[0-9]*<\/a><\/td>\(.*\)<\/td>$/\1/p" tmp | sed "s/<[^>]*>//g" >old.out && sed -n "s/^]*>[0-9]*<\/a><\/td>\(.*\)<\/td><\/tr>$/\1/p" tmp | sed "s/<[^>]*>//g" >new.out && git -C repos/lcs show HEAD~1:lines.txt >expect && test_cmp expect old.out && git -C repos/lcs show HEAD:lines.txt >expect && test_cmp expect new.out ' # Comparing the second pair below reads cells the first one wrote, and a cell # left over from it would tip a tie there and mark the wrong characters. test_expect_success 'a short pair after a longer one marks its own characters' ' mkrepo repos/pair 1 && ( cd repos/pair && test_write_lines bcde xa >pair.txt && git add pair.txt && git commit -m "add pair.txt" && test_write_lines abcd ax >pair.txt && git commit -am "change pair.txt" ) && cgitrc_repo pairrc pair && cgit_ok pairrc "url=pair/diff/&dt=1" >tmp && sed -n "s/^]*>[0-9]*<\/a><\/td>//p" tmp | tr -d "\047" >actual && cat >expect <<-\EOF && bcde abcd
xa ax
5
onlyONLY
gone
oneONE
two
$(printf "%0130d" 0)$(printf "%0129d1" 0)
a b
Binary files differ
This diff is too large to be rendered inline. View it on its own page.
file-5
" tmp ' test_expect_success 'set up a change to whitespace alone' ' mkrepo repos/space 1 && ( cd repos/space && echo "a b" >space.txt && git add space.txt && git commit -m "add space.txt" && echo "a b" >space.txt && git commit -am "widen space.txt" ) && cgitrc_repo spacerc space ' test_expect_success 'ignorews=1 hides a change to whitespace alone' ' cgit_ok spacerc "url=space/diff/" >tmp && grep "
@@ -1 +1 @@
" tmp && cgit_ok spacerc "url=space/diff/&ignorews=1" >tmp && grep "diff --git a/space.txt b/space.txt" tmp && ! grep "class=.hunk." tmp ' # The context is capped, since context lines do not count against # max-diff-lines and an unbounded width would render the whole blob. test_expect_success 'context sets the lines around a change, up to a cap' ' mkrepo repos/wide 1 && ( cd repos/wide && test_seq 1 100 >wide.txt && git add wide.txt && git commit -m "add wide.txt" && test_seq 1 100 | sed s/^50$/fifty/ >wide.txt && git commit -am "change wide.txt" ) && cgitrc_repo widerc wide && cgit_ok widerc "url=wide/diff/" >tmp && grep "
@@ -47,7 +47,7 @@
" tmp && cgit_ok widerc "url=wide/diff/&context=1" >tmp && grep "
@@ -49,3 +49,3 @@
" tmp && cgit_ok widerc "url=wide/diff/&context=999" >tmp && grep "
@@ -10,81 +10,81 @@
" tmp ' test_expect_success 'side-by-side-diffs=1 makes side by side the default' ' cgitrc_repo ssrc wide side-by-side-diffs=1 && cgit_ok ssrc "url=wide/diff/" >tmp && grep "
" tmp && cgit_ok ssrc "url=wide/diff/&dt=0" >tmp && grep "
" tmp ' # Exact renames are found whatever the limit, so both of these change a line. # Two sources against two destinations is past a limit of one, and 0 sets no # limit at all. test_expect_success 'set up two renames that are not exact' ' mkrepo repos/renames 1 && ( cd repos/renames && test_seq 1 10 >a.txt && test_seq 11 20 >b.txt && git add a.txt b.txt && git commit -m "add a.txt and b.txt" && git mv a.txt c.txt && git mv b.txt d.txt && echo more >>c.txt && echo more >>d.txt && git commit -am "rename both" ) ' test_expect_success 'rename-limit bounds the renames a diff looks for' ' cgitrc_repo renamesrc renames && cgit_ok renamesrc "url=renames/diff/" >tmp && grep " (renamed from a.txt)" tmp && grep " (renamed from b.txt)" tmp && cgitrc_repo renamesrc renames rename-limit=1 && cgit_ok renamesrc "url=renames/diff/" >tmp && grep "diff --git a/c.txt b/c.txt
new file mode 100644" tmp && grep "diff --git a/a.txt b/a.txt
deleted file mode 100644" tmp && ! grep "renamed from" tmp && cgitrc_repo renamesrc renames rename-limit=0 && cgit_ok renamesrc "url=renames/diff/" >tmp && grep " (renamed from a.txt)" tmp && grep " (renamed from b.txt)" tmp ' # The diffstat links a renamed file by its new name, and so does the log of # that file, but the old name lies outside a diff limited to the new one. That # diff runs over the whole commit to find the rename, so the commit changes # another file as well, which the limit still has to leave out. test_expect_success 'set up a renamed file' ' mkrepo_renamed repos/moved "echo changed >file-1" && cgitrc_repo movedrc moved ' test_expect_success 'the diff of a renamed file shows the rename alone' ' cgit_ok movedrc "url=moved/diff/new.txt" >tmp && grep "diff --git a/old.txt b/new.txt" tmp && grep " (renamed from old.txt)" tmp && grep "
1 file changed, 0 insertions, 0 deletions
" tmp && ! grep "new file mode" tmp && ! grep "a/file-1 b/file-1" tmp ' test_expect_success 'so does the commit page limited to the new name' ' cgit_ok movedrc "url=moved/commit/new.txt" >tmp && grep "diff --git a/old.txt b/new.txt" tmp && grep "
1 file changed, 0 insertions, 0 deletions
" tmp && ! grep "new file mode" tmp && ! grep "a/file-1 b/file-1" tmp ' # Following a file diffs the whole commit and keeps the pairs on that path, # and the header still names the path rather than the empty limit the walk # runs under. test_expect_success 'a followed file is diffed as the rename alone' ' cgitrc_repo followrc moved enable-follow-links=1 && cgit_ok followrc "url=moved/diff/new.txt&follow=1" >tmp && grep "diff --git a/old.txt b/new.txt" tmp && grep "Diffstat (limited to .new.txt.)" tmp && grep "
1 file changed, 0 insertions, 0 deletions
" tmp && ! grep "a/file-1 b/file-1" tmp && cgit_ok followrc "url=moved/commit/new.txt&follow=1" >tmp && grep "diff --git a/old.txt b/new.txt" tmp && grep "Diffstat (limited to .new.txt.)" tmp && ! grep "a/file-1 b/file-1" tmp ' # A followed path is matched as a pathspec would match it, the file itself or # whatever lies below it, rather than every path starting with the same # characters. test_expect_success 'a followed path takes in no file it only prefixes' ' mkrepo repos/prefixed 1 && ( cd repos/prefixed && mkdir small.d && echo c >small.c && echo cpp >small.cpp && echo d >small.d/f && git add . && git commit -m "add the files" && echo C >small.c && echo CPP >small.cpp && echo D >small.d/f && git commit -am "change the files" ) && cgitrc_repo prefixedrc prefixed enable-follow-links=1 && cgit_ok prefixedrc "url=prefixed/diff/small.c&follow=1" >tmp && grep "diff --git a/small.c b/small.c" tmp && ! grep "small.cpp" tmp && cgit_ok prefixedrc "url=prefixed/diff/small.d&follow=1" >tmp && grep "diff --git a/small.d/f b/small.d/f" tmp && ! grep "small.c" tmp ' test_expect_success 'following with no path limits nothing' ' cgit_ok followrc "url=moved/commit/&follow=1" >tmp && grep "diff --git a/file-1 b/file-1" tmp && grep "
]*>Diffstat
" tmp ' test_expect_success 'a file added outright still shows as new' ' added=$(git -C repos/moved rev-parse HEAD~1) && cgit_ok movedrc "url=moved/diff/old.txt&id=$added" >tmp && grep "new file mode 100644" tmp && grep "
+10
" tmp ' test_done