diff options
-rw-r--r-- | Build/source/texk/texlive/linked_scripts/Makefile.am | 1 | ||||
-rw-r--r-- | Build/source/texk/texlive/linked_scripts/Makefile.in | 1 | ||||
-rw-r--r-- | Build/source/texk/texlive/linked_scripts/scripts.lst | 1 | ||||
-rwxr-xr-x | Build/source/texk/texlive/linked_scripts/xput/xput | 520 | ||||
l--------- | Master/bin/aarch64-linux/xput | 1 | ||||
l--------- | Master/bin/amd64-freebsd/xput | 1 | ||||
l--------- | Master/bin/amd64-netbsd/xput | 1 | ||||
l--------- | Master/bin/armhf-linux/xput | 1 | ||||
l--------- | Master/bin/i386-cygwin/xput | 1 | ||||
l--------- | Master/bin/i386-freebsd/xput | 1 | ||||
l--------- | Master/bin/i386-linux/xput | 1 | ||||
l--------- | Master/bin/i386-netbsd/xput | 1 | ||||
l--------- | Master/bin/i386-solaris/xput | 1 | ||||
l--------- | Master/bin/universal-darwin/xput | 1 | ||||
l--------- | Master/bin/x86_64-cygwin/xput | 1 | ||||
l--------- | Master/bin/x86_64-darwinlegacy/xput | 1 | ||||
l--------- | Master/bin/x86_64-linux/xput | 1 | ||||
l--------- | Master/bin/x86_64-linuxmusl/xput | 1 | ||||
l--------- | Master/bin/x86_64-solaris/xput | 1 | ||||
-rwxr-xr-x | Master/tlpkg/libexec/ctan2tds | 2 | ||||
-rw-r--r-- | Master/tlpkg/tlpsrc/xput.tlpsrc | 1 |
21 files changed, 540 insertions, 1 deletions
diff --git a/Build/source/texk/texlive/linked_scripts/Makefile.am b/Build/source/texk/texlive/linked_scripts/Makefile.am index 157368683e2..963669255a7 100644 --- a/Build/source/texk/texlive/linked_scripts/Makefile.am +++ b/Build/source/texk/texlive/linked_scripts/Makefile.am @@ -99,6 +99,7 @@ texmf_shell_scripts = \ tikztosvg/tikztosvg \ typeoutfileinfo/typeoutfileinfo.sh \ wordcount/wordcount.sh \ + xput/xput \ xput/xputserver texmf_other_scripts = \ diff --git a/Build/source/texk/texlive/linked_scripts/Makefile.in b/Build/source/texk/texlive/linked_scripts/Makefile.in index d474578f96e..5589afd5521 100644 --- a/Build/source/texk/texlive/linked_scripts/Makefile.in +++ b/Build/source/texk/texlive/linked_scripts/Makefile.in @@ -313,6 +313,7 @@ texmf_shell_scripts = \ tikztosvg/tikztosvg \ typeoutfileinfo/typeoutfileinfo.sh \ wordcount/wordcount.sh \ + xput/xput \ xput/xputserver texmf_other_scripts = \ diff --git a/Build/source/texk/texlive/linked_scripts/scripts.lst b/Build/source/texk/texlive/linked_scripts/scripts.lst index 5d7f62926b1..35b860a8f13 100644 --- a/Build/source/texk/texlive/linked_scripts/scripts.lst +++ b/Build/source/texk/texlive/linked_scripts/scripts.lst @@ -40,6 +40,7 @@ texosquery/texosquery-jre8.sh tikztosvg/tikztosvg typeoutfileinfo/typeoutfileinfo.sh wordcount/wordcount.sh +xput/xput xput/xputserver a2ping/a2ping.pl accfonts/mkt1font diff --git a/Build/source/texk/texlive/linked_scripts/xput/xput b/Build/source/texk/texlive/linked_scripts/xput/xput new file mode 100755 index 00000000000..57203c7a5da --- /dev/null +++ b/Build/source/texk/texlive/linked_scripts/xput/xput @@ -0,0 +1,520 @@ +#!/bin/sh +# +# Copyright (C) 2022 by Friedemann Bartels +# +# This file may be distributed and/or modified under the +# conditions of the LaTeX Project Public License, either +# version 1.3c of this license or (at your option) any later +# version. The latest version of this license is in: +# +# http://www.latex-project.org/lppl.txt +# +# and version 1.3c or later is part of all distributions of +# LaTeX version 2008/05/04 or later. +# + +version=1.0.2 + +OK="$( tput setaf 2 )•$( tput sgr0 )" +FAILED="$( tput setaf 1 )$( tput bold )x$( tput sgr0 )" +NEW="$( tput setaf 3 )$( tput bold )+$( tput sgr0 )" +REMOVED="$( tput setaf 5 )$( tput bold )-$( tput sgr0 )" +ERROR="$( tput setaf 1 )$( tput bold )!$( tput sgr0 )" + +_playok() { + if [ -f /System/Library/Sounds/Glass.aiff ]; then + afplay /System/Library/Sounds/Glass.aiff >/dev/null 2>&1 + fi +} + +_playhm() { + if [ -f /System/Library/Sounds/Basso.aiff ]; then + afplay /System/Library/Sounds/Basso.aiff >/dev/null 2>&1 + fi +} + +_playerror() { + if [ -f /System/Library/Sounds/Sosumi.aiff ]; then + afplay /System/Library/Sounds/Sosumi.aiff >/dev/null 2>&1 + fi +} + +_gettime() { + if command -v gdate &> /dev/null; then + echo $( gdate +%s%3N ) + else + if command -v date &> /dev/null; then + milliseconds=$( date +%3N ) + if [ $milliseconds = 3N ]; then + echo $(( SECONDS * 1000 )) + else + echo $( date +%s%3N ) + fi + else + echo $(( SECONDS * 1000 )) + fi + fi +} + +_starttimer() { + starttime=$( _gettime ) +} + +_stoptimer() { + endtime=$( _gettime ) + + elapsedtime=$(( endtime - starttime )) + elapsedseconds=$(( elapsedtime / 1000 )) + elapsedmilliseconds=$(( elapsedtime % 1000 )) + elapsed=$elapsedseconds.$( printf "%03d" "$elapsedmilliseconds" ) +} + +test() { + _starttimer + tmpdir=$( mktemp -d 2>/dev/null )/textest$( date "+%Y%m%d%H%M%S" )$RANDOM + mkdir $tmpdir + + if [ $3 = true ] && [ -d cache ]; then + rm -rf cache + fi + + okcount=0 + failedcount=0 + newcount=0 + removedcount=0 + fileokcount=0 + filefailedcount=0 + defaultfiller=23 + + echo "" + for entry in *$5*.tex + do + if [ $entry != "*$5*.tex" ]; then + name=$( echo $entry | sed -e 's/\.tex$//g' ) + if [ ${name:0:1} != _ ]; then + printf "$( tput sgr0 )$name" + + runtwice=0 + if [ "${name:$(( ${#name} - 2 )):2}" = "@2" ]; then + runtwice=1 + fi + + if [ "$4" != "xelatex" ]; then + name="$name.$4" + fi + + passed=1 + rm -f $name.failed.* + + cp $entry $tmpdir/$name.tex + shell="" + if [ $1 = true ]; then + shell="--shell-escape" + fi + $4 -interaction=batchmode $shell --output-directory $tmpdir $tmpdir/$name.tex > /dev/null + if [ $? -eq 1 ]; then + passed=0 + fi + if [ $runtwice -eq 1 ]; then + $4 -interaction=batchmode $shell --output-directory $tmpdir $tmpdir/$name.tex > /dev/null + if [ $? -eq 1 ]; then + passed=0 + fi + fi + + magick convert -density $2 -quiet $tmpdir/$name.pdf $tmpdir/$name.png + if [ -f "$tmpdir/$name.png" ]; then + mv $tmpdir/$name.png $tmpdir/$name-0.png + fi + + if [ -f "$name.approved.pdf" ]; then + magick convert -density $2 -quiet $name.approved.pdf $tmpdir/$name.approved.png + if [ -f "$tmpdir/$name.approved.png" ]; then + mv $tmpdir/$name.approved.png $tmpdir/$name.approved-0.png + fi + fi + + if [ $passed -eq 0 ]; then + filler=$(( defaultfiller - ${#name} - 2 )) + else + filler=$(( defaultfiller - ${#name} )) + fi + while [ 0 -le $filler ]; do + printf " " + filler=$(( filler - 1 )) + done + if [ $passed -eq 0 ]; then + printf " $ERROR" + fi + + index=0 + while [ -f "$tmpdir/$name-$index.png" ]; do + if [ -f "$tmpdir/$name.approved-$index.png" ]; then + changedpixels=$( magick compare -quiet -metric AE $tmpdir/$name-$index.png $tmpdir/$name.approved-$index.png null: 2>&1 ) + if [ $changedpixels -eq 0 ]; then + okcount=$(( okcount + 1 )) + printf " $OK" + else + failedcount=$(( failedcount + 1 )) + passed=0 + printf " $FAILED" + magick compare -quiet $tmpdir/$name-$index.png $tmpdir/$name.approved-$index.png $name.failed.$(( index + 1 )).png + if [ -f "$tmpdir/$name.pdf" ]; then + mv $tmpdir/$name.pdf $name.failed.pdf + fi + fi + else + newcount=$(( newcount + 1 )) + passed=0 + printf " $NEW" + mv $tmpdir/$name-$index.png $name.failed.$(( index + 1 )).png + if [ -f "$tmpdir/$name.pdf" ]; then + mv $tmpdir/$name.pdf $name.failed.pdf + fi + fi + index=$(( index + 1 )) + if [ `expr $index % 20` -eq 0 ] && [ -f "$tmpdir/$name-$index.png" ]; then + echo "" + filler=$defaultfiller + while [ 0 -le $filler ]; do + printf " " + filler=$(( filler - 1 )) + done + fi + done + while [ -f "$tmpdir/$name.approved-$index.png" ]; do + removedcount=$(( removedcount + 1 )) + passed=0 + printf " $REMOVED" + mv $tmpdir/$name.approved-$index.png $name.failed.$(( index + 1 )).png + if [ -f "$tmpdir/$name.pdf" ]; then + mv $tmpdir/$name.pdf $name.failed.pdf + fi + index=$(( index + 1 )) + if [ `expr $index % 20` -eq 0 ] && [ -f "$tmpdir/$name.approved-$index.png" ]; then + echo "" + filler=$defaultfiller + while [ 0 -le $filler ]; do + printf " " + filler=$(( filler - 1 )) + done + fi + done + + if [ $passed -eq 1 ]; then + fileokcount=$(( fileokcount + 1 )) + else + filefailedcount=$(( filefailedcount + 1 )) + fi + + echo "" + fi + fi + done + + rm -rf $tmpdir + _stoptimer + seconds=$( printf "%.1f" "$elapsed" ) + + filecount=$(( fileokcount + filefailedcount )) + + if [ $filecount -gt 0 ]; then + echo "" + fi + if [ $filecount -eq $fileokcount ]; then + if [ $filecount -eq 0 ]; then + _playhm & + echo "$( tput sgr0 )Tested 0 files 🧐." + else + _playok & + echo "$( tput sgr0 )Successfully tested $filecount files in $seconds seconds 🎉." + fi + echo "" + else + _playerror & + echo "$( tput sgr0 )Tested $filecount files in $seconds seconds." + echo "" + + if [ $fileokcount -gt 0 ]; then + filler=$(( 6 + ${#filecount} - ${#fileokcount} )) + while [ 0 -le $filler ]; do + printf " " + filler=$(( filler - 1 )) + done + printf "$( tput setaf 2 )$fileokcount OK$( tput sgr0 )" + echo "" + fi + if [ $filefailedcount -gt 0 ]; then + filler=$(( 6 + ${#filecount} - ${#filefailedcount} )) + while [ 0 -le $filler ]; do + printf " " + filler=$(( filler - 1 )) + done + printf "$( tput setaf 1 )$filefailedcount Failed$( tput sgr0 )" + echo "" + fi + echo "" + exit 1 + fi +} + +approve() { + filecount=0 + + suffix="" + if [ "$1" != "xelatex" ]; then + suffix=".$1" + fi + + echo "" + for entry in *$2*$suffix.failed.pdf + do + if [ $entry != "*$2*$suffix.failed.pdf" ]; then + filecount=$(( filecount + 1 )) + name=$( echo $entry | sed -e "s/$suffix.failed.pdf//" ) + echo $name + rm -f $name$suffix.approved.pdf + if [ -f "$name.aux" ]; then + cp $name$suffix.failed.pdf $name$suffix.approved.pdf + else + mv $name$suffix.failed.pdf $name$suffix.approved.pdf + fi + + rm -f $name$suffix.failed.* + fi + done + + if [ $filecount -gt 0 ]; then + echo "" + fi + if [ $filecount -eq 1 ]; then + echo "Approved 1 file." + else + echo "Approved $filecount files." + fi + echo "" +} + +compare() { + filea=$2 + fileb=$3 + tmpdir=$( mktemp -d 2>/dev/null)/textest$( date "+%Y%m%d%H%M%S" )$RANDOM + mkdir $tmpdir + + namea=$( echo $filea | sed -e 's/\.\///g' | sed -e 's/\.pdf$//g' ) + nameb=$( echo $fileb | sed -e 's/\.\///g' | sed -e 's/\.pdf$//g' ) + basenamea=$(basename $namea) + basenameb=$(basename $nameb) + + rm -f $namea.diff.*.png + + spacer="" + if [ -f "$filea" ]; then + if [ -f "$fileb" ]; then + magick convert -density $1 -quiet $filea $tmpdir/$basenamea.png + if [ -f "$tmpdir/$basenamea.png" ]; then + mv $tmpdir/$basenamea.png $tmpdir/$basenamea-0.png + fi + magick convert -density $1 -quiet $fileb $tmpdir/$basenameb.png + if [ -f "$tmpdir/$basenameb.png" ]; then + mv $tmpdir/$basenameb.png $tmpdir/$basenameb-0.png + fi + + index=0 + while [ -f "$tmpdir/$basenamea-$index.png" ]; do + if [ -f "$tmpdir/$basenameb-$index.png" ]; then + changedpixels=$( magick compare -quiet -metric AE $tmpdir/$basenamea-$index.png $tmpdir/$basenameb-$index.png null: 2>&1 ) + if [ $changedpixels -eq 0 ]; then + printf "$spacer$OK" + spacer=" " + else + printf "$spacer$FAILED" + spacer=" " + magick compare -quiet $tmpdir/$basenamea-$index.png $tmpdir/$basenameb-$index.png $namea.diff.$(( index + 1 )).png + fi + else + printf "$spacer$NEW" + spacer=" " + fi + index=$(( index + 1 )) + done + while [ -f "$tmpdir/$basenameb-$index.png" ]; do + printf "$spacer$REMOVED" + spacer=" " + index=$(( index + 1 )) + done + echo "" + else + echo "File $fileb not found." + fi + else + echo "File $filea not found." + fi + + rm -rf $tmpdir +} + +perf() { + if [ -f $4 ]; then + tmpdir=$( mktemp -d 2>/dev/null )/textestperf$( date "+%Y%m%d%H%M%S" )$RANDOM + mkdir $tmpdir + basename=$(basename $4) + + if [ $1 = true ] && [ -d cache ]; then + rm -rf cache + fi + + cp $4 $tmpdir + shell="" + if [ $2 = true ]; then + shell="--shell-escape" + fi + _starttimer + $3 -interaction=batchmode $shell --output-directory $tmpdir $tmpdir/$basename > /dev/null + _stoptimer + echo "$elapsed" + + rm -rf $tmpdir + else + echo "File $4 not found." + fi +} + +usage() { + cat <<HELP_USAGE +usage: xput test [-cs] [-e ENGINE] [-d DENSITY] [PATTERN] + xput approve [-e ENGINE] [PATTERN] + xput compare [-d DENSITY] FILE FILE + xput perf [-cs] [-e ENGINE] FILE + xput --help + xput --version + + -c clear cache + -s enable shell escape + -d DENSITY density in ppi (default 72) + -e ENGINE latex engine (default xelatex) + + Running \`xput test\` creates pdf files for all tex files matching the + pattern and performs a visual regression test. If no pattern is specified, + all files in the current directory are tested except for files whose names + begin with an underscore. + + Running \`xput approve\` replaces the reference files with the test files. + + Running \`xput compare\` creates a visual diff for two pdf files. + + Running \`xput perf\` measures the time for creating a pdf file from the + given tex file. + + Running \`xput --help\` returns this man page. + + Running \`xput --version\` returns the Xput version. +HELP_USAGE +} + +case "$1" in +test) + shift + + density=72 + shell=false + clear=false + engine=xelatex + + while getopts ":e:d:sc" arg; do + case "${arg}" in + c) + clear=true + ;; + d) + density="${OPTARG}" + ;; + e) + engine="${OPTARG}" + ;; + s) + shell=true + ;; + ?) + echo "Invalid option: -${OPTARG}." + ;; + esac + done + + shift "$(( OPTIND - 1 ))" + + test $shell $density $clear $engine $1 + ;; +approve) + shift + engine=xelatex + + while getopts ":e:" arg; do + case "${arg}" in + e) + engine="${OPTARG}" + ;; + ?) + echo "Invalid option: -${OPTARG}." + ;; + esac + done + + shift "$(( OPTIND - 1 ))" + + approve $engine $1 + ;; +compare) + shift + + density=72 + + while getopts ":d:" arg; do + case "${arg}" in + d) + density="${OPTARG}" + ;; + ?) + echo "Invalid option: -${OPTARG}." + ;; + esac + done + + shift "$(( OPTIND - 1 ))" + + compare $density $1 $2 + ;; +perf) + shift + + shell=false + clear=false + engine=xelatex + + while getopts ":e:sc" arg; do + case "${arg}" in + c) + clear=true + ;; + e) + engine="${OPTARG}" + ;; + s) + shell=true + ;; + ?) + echo "Invalid option: -${OPTARG}." + ;; + esac + done + + shift "$(( OPTIND - 1 ))" + + perf $clear $shell $engine $1 + ;; +--version) + echo Xput $version + ;; +*) + usage +esac diff --git a/Master/bin/aarch64-linux/xput b/Master/bin/aarch64-linux/xput new file mode 120000 index 00000000000..95fb47cf1ca --- /dev/null +++ b/Master/bin/aarch64-linux/xput @@ -0,0 +1 @@ +../../texmf-dist/scripts/xput/xput
\ No newline at end of file diff --git a/Master/bin/amd64-freebsd/xput b/Master/bin/amd64-freebsd/xput new file mode 120000 index 00000000000..95fb47cf1ca --- /dev/null +++ b/Master/bin/amd64-freebsd/xput @@ -0,0 +1 @@ +../../texmf-dist/scripts/xput/xput
\ No newline at end of file diff --git a/Master/bin/amd64-netbsd/xput b/Master/bin/amd64-netbsd/xput new file mode 120000 index 00000000000..95fb47cf1ca --- /dev/null +++ b/Master/bin/amd64-netbsd/xput @@ -0,0 +1 @@ +../../texmf-dist/scripts/xput/xput
\ No newline at end of file diff --git a/Master/bin/armhf-linux/xput b/Master/bin/armhf-linux/xput new file mode 120000 index 00000000000..95fb47cf1ca --- /dev/null +++ b/Master/bin/armhf-linux/xput @@ -0,0 +1 @@ +../../texmf-dist/scripts/xput/xput
\ No newline at end of file diff --git a/Master/bin/i386-cygwin/xput b/Master/bin/i386-cygwin/xput new file mode 120000 index 00000000000..95fb47cf1ca --- /dev/null +++ b/Master/bin/i386-cygwin/xput @@ -0,0 +1 @@ +../../texmf-dist/scripts/xput/xput
\ No newline at end of file diff --git a/Master/bin/i386-freebsd/xput b/Master/bin/i386-freebsd/xput new file mode 120000 index 00000000000..95fb47cf1ca --- /dev/null +++ b/Master/bin/i386-freebsd/xput @@ -0,0 +1 @@ +../../texmf-dist/scripts/xput/xput
\ No newline at end of file diff --git a/Master/bin/i386-linux/xput b/Master/bin/i386-linux/xput new file mode 120000 index 00000000000..95fb47cf1ca --- /dev/null +++ b/Master/bin/i386-linux/xput @@ -0,0 +1 @@ +../../texmf-dist/scripts/xput/xput
\ No newline at end of file diff --git a/Master/bin/i386-netbsd/xput b/Master/bin/i386-netbsd/xput new file mode 120000 index 00000000000..95fb47cf1ca --- /dev/null +++ b/Master/bin/i386-netbsd/xput @@ -0,0 +1 @@ +../../texmf-dist/scripts/xput/xput
\ No newline at end of file diff --git a/Master/bin/i386-solaris/xput b/Master/bin/i386-solaris/xput new file mode 120000 index 00000000000..95fb47cf1ca --- /dev/null +++ b/Master/bin/i386-solaris/xput @@ -0,0 +1 @@ +../../texmf-dist/scripts/xput/xput
\ No newline at end of file diff --git a/Master/bin/universal-darwin/xput b/Master/bin/universal-darwin/xput new file mode 120000 index 00000000000..95fb47cf1ca --- /dev/null +++ b/Master/bin/universal-darwin/xput @@ -0,0 +1 @@ +../../texmf-dist/scripts/xput/xput
\ No newline at end of file diff --git a/Master/bin/x86_64-cygwin/xput b/Master/bin/x86_64-cygwin/xput new file mode 120000 index 00000000000..95fb47cf1ca --- /dev/null +++ b/Master/bin/x86_64-cygwin/xput @@ -0,0 +1 @@ +../../texmf-dist/scripts/xput/xput
\ No newline at end of file diff --git a/Master/bin/x86_64-darwinlegacy/xput b/Master/bin/x86_64-darwinlegacy/xput new file mode 120000 index 00000000000..95fb47cf1ca --- /dev/null +++ b/Master/bin/x86_64-darwinlegacy/xput @@ -0,0 +1 @@ +../../texmf-dist/scripts/xput/xput
\ No newline at end of file diff --git a/Master/bin/x86_64-linux/xput b/Master/bin/x86_64-linux/xput new file mode 120000 index 00000000000..95fb47cf1ca --- /dev/null +++ b/Master/bin/x86_64-linux/xput @@ -0,0 +1 @@ +../../texmf-dist/scripts/xput/xput
\ No newline at end of file diff --git a/Master/bin/x86_64-linuxmusl/xput b/Master/bin/x86_64-linuxmusl/xput new file mode 120000 index 00000000000..95fb47cf1ca --- /dev/null +++ b/Master/bin/x86_64-linuxmusl/xput @@ -0,0 +1 @@ +../../texmf-dist/scripts/xput/xput
\ No newline at end of file diff --git a/Master/bin/x86_64-solaris/xput b/Master/bin/x86_64-solaris/xput new file mode 120000 index 00000000000..95fb47cf1ca --- /dev/null +++ b/Master/bin/x86_64-solaris/xput @@ -0,0 +1 @@ +../../texmf-dist/scripts/xput/xput
\ No newline at end of file diff --git a/Master/tlpkg/libexec/ctan2tds b/Master/tlpkg/libexec/ctan2tds index 8087b10e413..e1f540463c5 100755 --- a/Master/tlpkg/libexec/ctan2tds +++ b/Master/tlpkg/libexec/ctan2tds @@ -3679,7 +3679,7 @@ $standardttf = '\.ttf|\.TTC'; 'wordcount' => '\.sh$', 'wheretotrim' => '\.pl$', 'xindex' => 'xindex\.lua$', - 'xput' => 'xputserver$', + 'xput' => 'xput(server)?$', 'yplan' => 'yplan$', ); diff --git a/Master/tlpkg/tlpsrc/xput.tlpsrc b/Master/tlpkg/tlpsrc/xput.tlpsrc index ba0631802cf..f7b3a88e919 100644 --- a/Master/tlpkg/tlpsrc/xput.tlpsrc +++ b/Master/tlpkg/tlpsrc/xput.tlpsrc @@ -1 +1,2 @@ +binpattern f bin/${ARCH}/${PKGNAME} binpattern f bin/${ARCH}/${PKGNAME}server |