Skip to content

Commit

Permalink
[TASK] Build / CI: Get all exception codes of TYPO3 on CLI
Browse files Browse the repository at this point in the history
All exception codes of the current TYPO3 version can be output
to stdout without checking for missing and duplicate exception codes.

Therefore, the patch adds the `-p` option to the
duplicateExceptionCodeCheck.sh:

Build/Scripts/duplicateExceptionCodeCheck.sh -p

It is also added to runTests.sh:

Build/Scripts/runTests.sh -s listExceptionCodes

Resolves: #93499
Releases: master, 10.4, 9.5
Change-Id: I088d53bfbd8b5255b6516de3f546f3f914871ee1
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/67962
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: core-ci <typo3@b13.com>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
  • Loading branch information
alexander-nitsche authored and lolli42 committed Feb 17, 2021
1 parent 75fe0ee commit 1f46b0c
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 60 deletions.
217 changes: 157 additions & 60 deletions Build/Scripts/duplicateExceptionCodeCheck.sh
Expand Up @@ -4,12 +4,17 @@
#
# Find duplicate exception timestamps and list them.
# Additionally find exceptions that have no exception code.
# Optionally write the list of found exception codes to the standard output stream in JSON format.
#
# It expects to be run from the core root.
#
##########################

cd typo3/
# --------------------------
# --- default parameters ---
# --------------------------
print=0
scanPath="typo3/"

ignoreFiles=()
# auto generated file, shouldn't be checked
Expand All @@ -26,70 +31,162 @@ ignoreFiles+="sysext/frontend/Classes/Typolink/PageLinkBuilder.php"
# until AbstractController is removed
ignoreFiles+="sysext/extbase/Classes/Mvc/Controller/AbstractController.php"

foundNewFile=0
oldFilename=""
firstLineOfMatch=""
foundExceptionInFile=1
exceptionCodes=()
# ------------------------
# --- print usage info ---
# ------------------------
usage()
{
echo "Usage: $0 [options] "
echo " "
echo "No arguments/default: Check exception numbers for duplicates. "
echo " "
echo "Options: "
echo " -p "
echo " Specifies whether the list of exceptions found should "
echo " be output as JSON in the standard output stream. "
echo " "
echo " -h "
echo " Show this help. "
echo " "
exit 0
}

# grep
# '-r' recursive
# '--include '*.php'' in all .php files
# '-Pzoab' pcre regex, -zo remove all linebreaks for multiline match, treat all files as text, output position "filename:position: match", binary position
#
# (?:(?!Exception\()[\w\\])* negative lookahead. capture all alphanum and \ until we reach "Exception("
# eat "Exception("
# (?:(?!\);).|[\r\n])*\);[\r\n]+ negative lookahead again, eat everything including a \n until we reach the first ");", then line breaks

grep \
-r \
--include '*.php' \
-Pzoab \
'new (?:(?!Exception\()[\w\\])*Exception\((?:(?!\);).|[\r\n])*\);[\r\n]+' \
| \
while read line;
do
possibleFilename=`echo ${line} | cut -d':' -f1`
if [[ ${possibleFilename} =~ .php$ ]]; then
# the matched line consists of a file name match, we're dealing with a new match here.
foundNewFile=1
oldFilename=${currentFilename}
currentFilename=${possibleFilename}
else
foundNewFile=0
fi

# skip file if in blacklist
if [[ {$ignoreFiles[@]} =~ ${currentFilename} ]]; then
continue
fi
# -----------------------
# --- parsing of args ---
# -----------------------
OPTIND=1

# check for match in previous file name
if [[ ${foundNewFile} -eq 1 ]] && [[ ${foundExceptionInFile} -eq 0 ]]; then
echo "File: $oldFilename"
echo "The created exception contains no 10 digit exception code as second argument, in or below this line:"
echo "$firstLineOfMatch"
while getopts "hp" opt;do
case "$opt" in
h)
usage
;;
p)
print=1
;;
*)
exit 1
fi
;;
esac
done

shift $((OPTIND-1))

# reset found flag if we're handling new file
if [[ ${foundNewFile} -eq 1 ]]; then
foundExceptionInFile=0
firstLineOfMatch=${line}
# ------------------------------------------------
# --- print list of found exceptions to stdout ---
# ------------------------------------------------
print_exceptions() {
IFS=$'\n' sorted=($(sort -u <<<"${exceptionCodes[*]}")); unset IFS

local numExceptions=${#sorted[@]}

printf "{\n"
printf " \"exceptions\": {\n"
if [ ${numExceptions} -gt 0 ]; then
for (( i=0; i<${numExceptions}-1; i++ ));
do
printf " \"%s\":\"%s\",\n" "${sorted[$i]}" "${sorted[$i]}"
done
printf " \"%s\":\"%s\"\n" "${sorted[${numExceptions}-1]}" "${sorted[${numExceptions}-1]}"
fi
printf " },\n"
printf " \"total\":%s\n" "${numExceptions}"
printf "}\n"
}

# -------------------------------------------------------------------------------
# --- check PHP files recursively for missing and duplicate exception numbers ---
# -------------------------------------------------------------------------------
scan_exceptions() {
local foundNewFile=0
local oldFilename=""
local firstLineOfMatch=""
local foundExceptionInFile=1
local exceptionCodes=()

# grep
# '-r' recursive
# '--include '*.php'' in all .php files
# '-Pzoab' pcre regex, -zo remove all linebreaks for multiline match, treat all files as text, output position "filename:position: match", binary position
#
# (?:(?!Exception\()[\w\\])* negative lookahead. capture all alphanum and \ until we reach "Exception("
# eat "Exception("
# (?:(?!\);).|[\r\n])*\);[\r\n]+ negative lookahead again, eat everything including a \n until we reach the first ");", then line breaks

cd "$scanPath" || exit 1

# see if the line consists of an exception code
if [[ "$line" =~ .*([0-9]{10}).* ]]; then
foundExceptionInFile=1
exceptionCode=${BASH_REMATCH[1]}
# check if that code was registered already
if [[ {$exceptionCodes[@]} =~ ${exceptionCode} ]]; then
echo "Duplicate exception code ${exceptionCode} in file:"
echo ${currentFilename}
exit 1
grep \
-r \
--include '*.php' \
-Pzoab \
'new (?:(?!Exception\()[\w\\])*Exception\((?:(?!\);).|[\r\n])*\);[\r\n]+' \
| \
{
while read line;
do
possibleFilename=`echo ${line} | cut -d':' -f1`
if [[ ${possibleFilename} =~ .php$ ]]; then
# the matched line consists of a file name match, we're dealing with a new match here.
foundNewFile=1
oldFilename=${currentFilename}
currentFilename=${possibleFilename}
else
foundNewFile=0
fi

# skip file if in blacklist
if [[ {$ignoreFiles[@]} =~ ${currentFilename} ]]; then
continue
fi

# check for match in previous file name
if [[ ${foundNewFile} -eq 1 ]] && [[ ${foundExceptionInFile} -eq 0 ]]; then
if [ "$print" -ne "1" ]; then
# checking exception codes: exit
# listing exception codes: ignore
echo "File: $oldFilename"
echo "The created exception contains no 10 digit exception code as second argument, in or below this line:"
echo "$firstLineOfMatch"
exit 1
fi
fi

# reset found flag if we're handling new file
if [[ ${foundNewFile} -eq 1 ]]; then
foundExceptionInFile=0
firstLineOfMatch=${line}
fi

# see if the line consists of an exception code
if [[ "$line" =~ .*([0-9]{10}).* ]]; then
foundExceptionInFile=1
exceptionCode=${BASH_REMATCH[1]}
# check if that code was registered already
if [[ " ${exceptionCodes[@]} " =~ " ${exceptionCode} " ]]; then
if [ "$print" -ne "1" ]; then
# checking exception codes: exit
# listing exception codes: ignore
echo "Duplicate exception code ${exceptionCode} in file:"
echo ${currentFilename}
exit 1
fi
fi
exceptionCodes+=(${exceptionCode})
fi
done || exit 1

if [ "$print" -eq "1" ]; then
print_exceptions
fi
exceptionCodes+=${exceptionCode}
fi
done || exit 1

exit 0
exit 0
}

exitCode=$?

cd - > /dev/null

exit $exitCode
}

scan_exceptions
7 changes: 7 additions & 0 deletions Build/Scripts/runTests.sh
Expand Up @@ -119,6 +119,7 @@ Options:
- lintScss: SCSS linting
- lintTypescript: TS linting
- lintHtml: HTML linting
- listExceptionCodes: list core exception codes in JSON format
- phpstan: phpstan tests
- unit (default): PHP unit tests
- unitDeprecated: deprecated PHP unit tests
Expand Down Expand Up @@ -699,6 +700,12 @@ case ${TEST_SUITE} in
SUITE_EXIT_CODE=$?
docker-compose down
;;
listExceptionCodes)
setUpDockerComposeDotEnv
docker-compose run list_exception_codes
SUITE_EXIT_CODE=$?
docker-compose down
;;
phpstan)
setUpDockerComposeDotEnv
docker-compose run phpstan
Expand Down
17 changes: 17 additions & 0 deletions Build/testing-docker/local/docker-compose.yml
Expand Up @@ -1151,6 +1151,23 @@ services:
node_modules/grunt/bin/grunt eslint;
"
list_exception_codes:
image: typo3/core-testing-${DOCKER_PHP_IMAGE}:latest
user: ${HOST_UID}
volumes:
- ${CORE_ROOT}:${CORE_ROOT}
- ${HOST_HOME}:${HOST_HOME}
- /etc/passwd:/etc/passwd:ro
- /etc/group:/etc/group:ro
working_dir: ${CORE_ROOT}
command: >
/bin/sh -c "
if [ ${SCRIPT_VERBOSE} -eq 1 ]; then
set -x
fi
Build/Scripts/duplicateExceptionCodeCheck.sh -p;
"
phpstan:
image: typo3/core-testing-${DOCKER_PHP_IMAGE}:latest
user: ${HOST_UID}
Expand Down

0 comments on commit 1f46b0c

Please sign in to comment.