mirror of
https://github.com/moparisthebest/xeps
synced 2024-11-14 05:15:07 -05:00
bee4c93cd3
xmllint will return exit code 10 when an XPATH query finds no matches. With the changes in this commit, the script isn't stopped. Instead, it uses an empty value, which is likely to cause the validation checks (further down in the script) to fail.
206 lines
8.4 KiB
Bash
Executable File
206 lines
8.4 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Checks if provided file (filename to be provided as first argument) conforms to XEP-0001.
|
|
# See https://github.com/xsf/xeps/issues/1235
|
|
#
|
|
# Expected to be executed from the directory that holds all xep XML files.
|
|
# Requires one argument: the file name of the xep to be validated, eg:
|
|
#
|
|
# $ tools/validate-xep0001-conformance.sh xep-0010.xml
|
|
#
|
|
# exit status will be non-zero upon validation failure.
|
|
#
|
|
# requires: bash, xmllint, sort (supporting the '-V' argument)
|
|
|
|
set -euo pipefail
|
|
|
|
validation_result=0
|
|
|
|
# 1. Check DTD conformance against xep.dtd
|
|
xep_dtd="xep.dtd"
|
|
if xmllint --noout --dtdvalid "$xep_dtd" "$1"
|
|
then
|
|
echo "[PASS] DTD conformance against xep.dtd"
|
|
else
|
|
echo "[FAIL] DTD conformance against xep.dtd"
|
|
validation_result=1;
|
|
fi
|
|
|
|
file_name=$(basename -- "$1")
|
|
|
|
# The test for exit code equalling 10 detects when the XPATH evaluation yields no results. In that case, the execution
|
|
# should not fail immediately, but use an empty value instead (which will likely cause a validation failure further down).
|
|
header_number=$(xmllint --xpath '/xep/header/number/text()' --nowarning --dtdvalid "$xep_dtd" "$1") || test $?=10
|
|
header_status=$(xmllint --xpath '/xep/header/status/text()' --nowarning --dtdvalid "$xep_dtd" "$1") || test $?=10
|
|
header_type=$(xmllint --xpath '/xep/header/type/text()' --nowarning --dtdvalid "$xep_dtd" "$1") || test $?=10
|
|
header_approver=$(xmllint --xpath '/xep/header/approver/text()' --nowarning --dtdvalid "$xep_dtd" "$1") || test $?=10
|
|
header_revisions=$(xmllint --xpath '/xep/header/revision/version/text()' --nowarning --dtdvalid "$xep_dtd" "$1") || test $?=10
|
|
processing_instructions=$(xmllint --xpath '/processing-instruction("xml-stylesheet")' --nowarning --dtdvalid "$xep_dtd" "$1") || test $?=10
|
|
|
|
if echo "$file_name" | grep -Eq "^xep-[0-9]{4}.xml$"
|
|
then
|
|
echo "[INFO] The filename ('$file_name') matches 'xep-[0-9]{4}.xml'."
|
|
# 2. If the filename matches xep-[0-9]{4}.xml, check:
|
|
# 2.1 that the number in the filename equals /xep/header/number (XPath)
|
|
if [ "$file_name" = "xep-$header_number.xml" ]
|
|
then
|
|
echo "[PASS] The number in the filename ('$file_name') equals XPATH value /xep/header/number/text() ('$header_number')."
|
|
else
|
|
echo "[FAIL] The number in the filename ('$file_name') does not equals XPATH value /xep/header/number/text() ('$header_number') (but should)."
|
|
validation_result=1
|
|
fi
|
|
else
|
|
echo "[INFO] The filename ('$file_name') does not match 'xep-[0-9]{4}.xml'."
|
|
# 3. If the filename does not match xep-[0-9]{4}.xml, check:
|
|
# 3.1 That the /xep/header/status/text() (XPath) is ProtoXEP
|
|
if [ "$header_status" = "ProtoXEP" ]
|
|
then
|
|
echo "[PASS] XPATH value /xep/header/status/text() ('$header_status') equals 'ProtoXEP'."
|
|
else
|
|
echo "[FAIL] XPATH value /xep/header/status/text() ('$header_status') does not equal 'ProtoXEP' (but should)."
|
|
validation_result=1
|
|
fi
|
|
|
|
# 3.2 That the /xep/header/number/text() (XPath) is literally XXXX
|
|
if [ "$header_number" = "XXXX" ]
|
|
then
|
|
echo "[PASS] XPATH value /xep/header/number/text() ('$header_status') equals 'XXXX'."
|
|
else
|
|
echo "[FAIL] XPATH value /xep/header/number/text() ('$header_status') does not equal 'XXXX' (but should)."
|
|
validation_result=1
|
|
fi
|
|
|
|
# 3.3 That the name does not start with xep-[0-9]
|
|
if echo "$file_name" | grep -Eq "^xep-[0-9].*$"
|
|
then
|
|
echo "[FAIL] The filename ('$file_name') starts with 'xep-[0-9]' (but should not)."
|
|
validation_result=1
|
|
else
|
|
echo "[PASS] The filename ('$file_name') does not start with 'xep-[0-9]'."
|
|
fi
|
|
fi
|
|
|
|
# 4. Check that /xep/header/status/text() (XPath) is a defined status (see tools/xeplib.py for an enum)
|
|
case $header_status in
|
|
ProtoXEP | Experimental | Proposed | Draft | Active | Final | Retracted | Obsolete | Deferred | Rejected | Deprecated )
|
|
echo "[PASS] XPATH value /xep/header/status/text() ('$header_status') equals a defined status."
|
|
;;
|
|
*)
|
|
echo "[FAIL] XPATH value /xep/header/status/text() ('$header_status') does not equals a defined status (but should)."
|
|
validation_result=1
|
|
;;
|
|
esac
|
|
|
|
# 5. Check that /xep/header/type/text() (XPath) is defined in XEP-0001
|
|
# If the XEP number is less than 400, also accept some legacy values. To find which, see which you encounter in the XEP numbers below 400 :-).
|
|
|
|
# FIXME: lots of duplications here. Find a better solution.
|
|
case $file_name in
|
|
'xep-0001.xml' | 'xep-0002.xml' | 'xep-0019.xml' | 'xep-0053.xml' | 'xep-00143.xml' | 'xep-0182.xml' | 'xep-0345.xml' | 'xep-0381.xml' | 'xep-0429.xml' | 'xep-0458.xml' )
|
|
case $header_type in
|
|
Historical | Humorous | Informational | Organizational | 'Standards Track' | 'Procedural' )
|
|
echo "[PASS] XPATH value /xep/header/type/text() ('$header_type') equals a defined type."
|
|
;;
|
|
*)
|
|
echo "[FAIL] XPATH value /xep/header/type/text() ('$header_type') does not equals a defined type (but should)."
|
|
validation_result=1
|
|
;;
|
|
esac
|
|
;;
|
|
'xep-0006.xml' | 'xep-0010.xml' | 'xep-0069.xml' | 'xep-0139.xml' )
|
|
case $header_type in
|
|
Historical | Humorous | Informational | Organizational | 'Standards Track' | 'SIG Formation' )
|
|
echo "[PASS] XPATH value /xep/header/type/text() ('$header_type') equals a defined type."
|
|
;;
|
|
*)
|
|
echo "[FAIL] XPATH value /xep/header/type/text() ('$header_type') does not equals a defined type (but should)."
|
|
validation_result=1
|
|
;;
|
|
esac
|
|
;;
|
|
'xep-0007.xml' )
|
|
case $header_type in
|
|
Historical | Humorous | Informational | Organizational | 'Standards Track' | 'SIG Proposal' )
|
|
echo "[PASS] XPATH value /xep/header/type/text() ('$header_type') equals a defined type."
|
|
;;
|
|
*)
|
|
echo "[FAIL] XPATH value /xep/header/type/text() ('$header_type') does not equals a defined type (but should)."
|
|
validation_result=1
|
|
;;
|
|
esac
|
|
;;
|
|
* )
|
|
case $header_type in
|
|
Historical | Humorous | Informational | Organizational | 'Standards Track' )
|
|
echo "[PASS] XPATH value /xep/header/type/text() ('$header_type') equals a defined type."
|
|
;;
|
|
*)
|
|
echo "[FAIL] XPATH value /xep/header/type/text() ('$header_type') does not equals a defined type (but should)."
|
|
validation_result=1
|
|
;;
|
|
esac
|
|
;;
|
|
esac
|
|
|
|
# 6. Check that /xep/header/approver/text() (XPath) is either Board or Council
|
|
case $header_approver in
|
|
Board | Council )
|
|
echo "[PASS] XPATH value /xep/header/approver/text() ('$header_approver') equals either 'Board' or 'Council'."
|
|
;;
|
|
*)
|
|
echo "[FAIL] XPATH value /xep/header/approver/text() ('$header_approver') does not equals 'Board' or 'Council' (but should)."
|
|
validation_result=1
|
|
;;
|
|
esac
|
|
|
|
# 7. Check that the version numbers in the revision blocks are descending (from top to bottom in the document)
|
|
expected_revision_order=$(echo "$header_revisions" | tr " " "\n" | sort -Vr)
|
|
if [ "$expected_revision_order" = "$header_revisions" ]
|
|
then
|
|
echo "[PASS] Version numbers in the revision blocks are descending."
|
|
else
|
|
echo "[FAIL] Version numbers in the revision blocks are not ordered (descending from top to bottom in the document) (but should be)."
|
|
echo " Order found : $(echo $header_revisions)" # funky $() nesting to remove newlines.
|
|
echo " Expected was: $(echo $expected_revision_order)"
|
|
validation_result=1
|
|
fi
|
|
|
|
# 8. If the approver (see above) is Board, enforce that /xep/header/type is not Standards Track.
|
|
if [ "$header_approver" = "Board" ]
|
|
then
|
|
if [ "$header_type" = "Standards Track" ]
|
|
then
|
|
echo "[FAIL] XPATH value /xep/header/approver/text() ('$header_approver') is 'Board' but XPATH value /xep/header/type/text() is 'Standards Track' (it should not be)."
|
|
validation_result=1
|
|
else
|
|
echo "[PASS] XPATH value /xep/header/approver/text() ('$header_approver') is 'Board' and XPATH value /xep/header/type/text() is not 'Standards Track'."
|
|
fi
|
|
fi
|
|
|
|
# 9. Check that it uses the xep.xsl XML stylesheet.
|
|
if echo "$processing_instructions" | grep -Eq "href=['\"]xep.xsl['\"]"
|
|
then
|
|
echo "[PASS] xep.xsl XML stylesheet is used."
|
|
else
|
|
echo "[FAIL] xep.xsl XML stylesheet is not used (but should be)."
|
|
validation_result=1
|
|
fi
|
|
|
|
# 10. Check that it includes the correct legal notice (by checking for the entity reference)
|
|
if grep -q "&LEGALNOTICE;" "$1"
|
|
then
|
|
echo "[PASS] entity reference for the legal notice has been detected."
|
|
else
|
|
echo "[FAIL] entity reference for the legal notice has not been detected (but it should have been)."
|
|
validation_result=1
|
|
fi
|
|
|
|
echo ""
|
|
if [ $validation_result = 0 ]
|
|
then
|
|
echo "No issues found."
|
|
else
|
|
echo "Issues found!"
|
|
fi
|
|
exit $validation_result
|