#!/bin/sh
#SCRIPT=$(readlink -f "$0")
#SCRIPTPATH=$(dirname "$SCRIPT")
#. "$SCRIPTPATH/.dbwebb.version"
. "bin/.dbwebb.version"
TESTS=0
ASSERTS=0
FAULTS=0
ECHO="printf"
TMPFILE="/tmp/dbwebb-error$$"
#
# External tools
#
JSHINT="jshint"
HTMLHINT="htmlhint"
# Change this to csshint?
CSSHINT="htmlhint"
HTML_MINIFIER="html-minifier"
HTML_MINIFIER_OPTIONS="--minify-js --minify-css --use-short-doctype --remove-attribute-quotes --collapse-boolean-attributes --conservative-collapse --collapse-whitespace --remove-comments"
UGLIFYJS="uglifyjs"
UGLIFYJS_OPTIONS="--mangle --compress --screw-ie8 --comments"
CLEANCSS="cleancss --s1"
PYLINT="pylint -r n --rcfile ./.pylintrc"
#
# Settings for this script
#
umask 022
export NODE_PATH=/usr/local/lib/node_modules
#
# Print usage of script
#
printUsage()
{
$ECHO "\nUtility dbwebb-validate $VERSION by Mikael Roos, to validate and publish course results when done."
$ECHO "\n"
$ECHO "\nUsage: dbwebb-validate [options] <item>"
$ECHO "\n"
$ECHO "Options:"
$ECHO "\n"
$ECHO "\n -h Print this message and exit."
$ECHO "\n -i Ignore validation faults and proceed anyway."
$ECHO "\n -n Only validate, do not publish."
$ECHO "\n -e Do not check for installed tools.."
$ECHO "\n -m Do not chmod."
$ECHO "\n -t Do not test me-structure."
$ECHO "\n -r Print required external commands."
#$ECHO "\n -u user Validate a specific user."
$ECHO "\n -s Silent, limited output."
$ECHO "\n -v Print version and exit."
$ECHO "\n"
$ECHO "\nItem:"
$ECHO "\n"
$ECHO "\n kmom01 Validate (and publish) selected kmom."
$ECHO "\n kmom02 Validate (and publish) selected kmom."
$ECHO "\n kmom03 Validate (and publish) selected kmom."
$ECHO "\n kmom04 Validate (and publish) selected kmom."
$ECHO "\n kmom05 Validate (and publish) selected kmom."
$ECHO "\n kmom06 Validate (and publish) selected kmom."
$ECHO "\n kmom10 Validate (and publish) selected kmom."
$ECHO "\n me Validate (and publish) all kmoms."
$ECHO "\n tutorial Validate (and publish) the tutorial."
$ECHO "\n example Validate (and publish) the example programs."
$ECHO "\n all Validate (and publish) me, tutorial and example."
$ECHO "\n"
$ECHO "\nExample:"
$ECHO "\n"
$ECHO "\n $ dbwebb-validate kmom01"
$ECHO "\n $ dbwebb-validate -n kmom01"
$ECHO "\n $ dbwebb-validate me"
$ECHO "\n"
$ECHO "\n"
}
#
# Map command to path
#
mapCmdToDir()
{
CMD="$1"
RES=""
case "$CMD" in
example) RES="example" ;;
tutorial) RES="tutorial" ;;
me) RES="me" ;;
all) RES="all" ;;
kmom01) RES="me/kmom01" ;;
kmom02) RES="me/kmom02" ;;
kmom03) RES="me/kmom03" ;;
kmom04) RES="me/kmom04" ;;
kmom05) RES="me/kmom05" ;;
kmom06) RES="me/kmom06" ;;
kmom10) RES="me/kmom10" ;;
esac
if [ ! -z $RES ]; then
$ECHO "$RES"
return
fi
case "$COURSE" in
javascript1)
case "$CMD" in
sandbox) RES="me/kmom01/sandbox" ;;
hangman) RES="me/kmom06/hangman" ;;
lab1) RES="me/kmom02/lab1" ;;
lab2) RES="me/kmom03/lab2" ;;
lab3) RES="me/kmom04/lab3" ;;
lab4) RES="me/kmom04/lab4" ;;
lab5) RES="me/kmom05/lab5" ;;
flag1) RES="me/kmom02/flag1" ;;
flag2) RES="me/kmom03/flag2" ;;
flag3) RES="me/kmom04/flag3" ;;
flag4) RES="me/kmom05/flag4" ;;
flag5) RES="me/kmom06/flag5" ;;
baddie1) RES="me/kmom02/baddie1" ;;
baddie2) RES="me/kmom03/baddie2" ;;
baddie3) RES="me/kmom04/baddie3" ;;
#baddie4) RES="me/kmom05/baddie4" ;;
#baddie5) RES="me/kmom06/baddie5" ;;
esac
;;
python)
case "$CMD" in
hello) RES="me/kmom01/hello" ;;
plane) RES="me/kmom01/plane" ;;
lab1) RES="me/kmom02/lab1" ;;
lab2) RES="me/kmom03/lab2" ;;
lab3) RES="me/kmom04/lab3" ;;
lab4) RES="me/kmom05/lab4" ;;
lab5) RES="me/kmom06/lab5" ;;
lab6) RES="me/kmom06/lab6" ;;
marvin1) RES="me/kmom02/marvin1" ;;
marvin2) RES="me/kmom03/marvin2" ;;
marvin3) RES="me/kmom04/marvin3" ;;
marvin4) RES="me/kmom05/marvin4" ;;
marvin5) RES="me/kmom06/marvin5" ;;
game1) RES="me/kmom04/game1" ;;
game2) RES="me/kmom05/game2" ;;
game3) RES="me/kmom06/game3" ;;
esac
;;
*)
$ECHO "\n$MSG_FAILED Unknown Course. Error in config file.\n"
exit 1
;;
esac
if [ ! -z "$RES" ]; then
$ECHO "$RES"
return
fi
$ECHO "\n$MSG_FAILED Unknown combination of Course and Item: $COURSE $CMD.\n"
exit 1
}
#
# Test me/ to contain at least expected items
#
testMe()
{
TESTS=$(( $TESTS + 1 ))
CMD="$1"
DIRS=""
FILES=""
ME="$TARGET/me"
case $COURSE in
javascript1)
FILES="me.html redovisning.html"
KMOM01="kmom01 kmom01/sandbox"
KMOM02="kmom02 kmom02/flag1 kmom02/lab1 kmom02/baddie1"
KMOM03="kmom03 kmom03/flag2 kmom03/lab2 kmom03/baddie2"
KMOM04="kmom04 kmom04/flag3 kmom04/lab3 kmom04/lab4 kmom04/baddie3"
KMOM05="kmom05 kmom05/flag4 kmom05/lab5"
KMOM06="kmom06 kmom06/hangman"
KMOM10="kmom10"
;;
python)
FILES="me.cgi me.py redovisning.cgi redovisning.py"
KMOM01="kmom01 kmom01/hello kmom01/plane"
KMOM02="kmom02 kmom02/marvin1 kmom02/lab1"
KMOM03="kmom03 kmom03/marvin2 kmom03/lab2"
KMOM04="kmom04 kmom04/marvin3 kmom04/lab3 kmom04/game1"
KMOM05="kmom05 kmom05/marvin4 kmom05/lab4 kmom05/game2"
KMOM06="kmom06 kmom06/marvin5 kmom06/lab5 kmom06/game3"
KMOM10="kmom10"
;;
*)
FILES=""
;;
esac
case "$CMD" in
kmom01) DIRS="$KMOM01" ;;
kmom02) DIRS="$KMOM02" ;;
kmom03) DIRS="$KMOM03" ;;
kmom04) DIRS="$KMOM04" ;;
kmom05) DIRS="$KMOM05" ;;
kmom06) DIRS="$KMOM06" ;;
kmom10) DIRS="$KMOM10" ;;
me) DIRS="$KMOM01 $KMOM02 $KMOM03 $KMOM04 $KMOM05 $KMOM06 $KMOM10" ;;
all) DIRS="$KMOM01 $KMOM02 $KMOM03 $KMOM04 $KMOM05 $KMOM06 $KMOM10" ;;
*) DIRS=""; FILES="" ;;
esac
if [ -z "$DIRS$FILES" ]; then
return
fi
$ECHO "\n\nTesting Me-directory items."
for dir in $DIRS; do
#$ECHO "\n $dir"
assert 0 "[ -d $ME/$dir ]" "Missing directory: me/$dir"
done
for file in $FILES; do
#$ECHO "\n $file"
assert 0 "[ -f $ME/$file ]" "Missing file: me/$file"
done
}
#
# Perform an assert
#
assert()
{
EXPECTED=$1
TEST=$2
MESSAGE=$3
ASSERTS=$(( $ASSERTS + 1 ))
sh -c "$TEST" > "$TMPFILE" 2>&1
STATUS=$?
ERROR=$(cat $TMPFILE)
#if [ ! $STATUS -eq $EXPECTED ]; then
if [ \( ! $STATUS -eq $EXPECTED \) -o \( ! -z "$ERROR" \) ]; then
FAULTS=$(( $FAULTS + 1 ))
case $IGNORE_FAULTS in
yes) MSG="\n\n$MSG_WARNING $MESSAGE\n" ;;
no) MSG="\n\n$MSG_FAILED $MESSAGE\n" ;;
esac
$ECHO "$MSG"
[ -z "$ERROR" ] || $ECHO "$ERROR\n\n"
if [ $IGNORE_FAULTS = "no" ]; then
$ECHO "\nTests: $TESTS Asserts: $ASSERTS Faults: $FAULTS\n"
$ECHO "\nCorrect the fault and run the validation again.\n\n"
exit 1
fi
fi
return $STATUS
}
#
# Check for installed commands
#
checkCommand()
{
COMMAND=$1
#$ECHO "\nChecking $COMMAND"
if ! hash "$COMMAND" 2>/dev/null; then
$ECHO "\n I require $COMMAND but it's not installed. Ignoring."
#$ECHO >&2 "\nI require $COMMAND but it's not installed. Ignoring for now."
#$ECHO >&2 "\nUse the following command to see what is required to run this script"
#$ECHO >&2 "\n dbwebb-validate -r";
#$ECHO >&2 "\n";
#exit 1
fi
}
#
# Check for installed tools
#
CHECKTOOLS="no"
checkTools()
{
[ $CHECKTOOLS = "no" ] || return; CHECKTOOLS="yes"
$ECHO "\nCheck for installed tools."
checkCommand $PYLINT
checkCommand $HTMLHINT
checkCommand $CSSHINT
checkCommand $JSHINT
[ $PUBLISH = "yes" -o $IGNORE_FAULTS = "yes" ] || return
checkCommand $HTML_MINIFIER
checkCommand $UGLIFYJS
checkCommand $CLEANCSS
}
#
# Set proper rights for files and directories
#
setChmod()
{
$ECHO "\nUpdating chmod on file and dir."
for filename in $(find "$TARGET" -type d); do
chmod 755 "$filename"
done
chmod -R u+rw "$TARGET"
chmod -R go+r "$TARGET"
}
#
# Perform validation tests
#
validateHtmlCssJs()
{
TESTS=$(( $TESTS + 1 ))
DIR="$1"
SILENT="$2"
if [ -z "$SILENT" ]; then $ECHO "\nValidate $DIR."; fi
assert 0 "[ -d $THETARGET/$DIR ]" "Missing directory: $THETARGET/$DIR" || return
$ECHO "\n *.html using HTMLHint."
#find $TARGET/$DIR -type f -name '*.html' | while read filename; do assert 0 "$HTMLHINT $filename" "HTMLHINT failed: $filename"; done
for filename in $(find "$THETARGET/$DIR/" -type f -name '*.html'); do
assert 0 "$HTMLHINT $filename" "HTMLHINT failed: $filename"
done
#$ECHO "\n *.css using HTMLHint."
#find $TARGET/$DIR -type f -name '*.css' | while read filename; do assert 0 "$HTMLHINT $filename" "HTMLHINT failed: $filename"; done
$ECHO "\n *.js using JSHint."
#find $TARGET/$DIR -type f -name '*.js' | while read filename; do assert 0 "$JSHINT $filename" "JSHint failed: $filename"; done
for filename in $(find "$THETARGET/$DIR/" -type f -name '*.js'); do
assert 0 "$JSHINT $filename" "JSHint failed: $filename"
done
}
#
# Perform validation tests
#
validatePython()
{
TESTS=$(( $TESTS + 1 ))
DIR="$1"
SILENT="$2"
if [ -z "$SILENT" ]; then $ECHO "\nValidate $DIR."; fi
assert 0 "[ -d $THETARGET/$DIR ]" "Missing directory: $THETARGET/$DIR" || return
$ECHO "\n *.py using Pylint."
for filename in $(find "$THETARGET/$DIR/" -type f -name '*.py'); do
assert 0 "$PYLINT $filename" "pylint failed: $filename"
done
$ECHO "\n *.cgi using Pylint."
for filename in $(find "$THETARGET/$DIR/" -type f -name '*.cgi'); do
assert 0 "$PYLINT $filename" "pylint failed: $filename"
done
}
#
# Validete by all techniques
#
validate()
{
TESTS=$(( $TESTS + 1 ))
DIR="$1"
if [ "$DIR" = "all" ]; then
DIR="example tutorial me"
fi
$ECHO "\n\nValidate $DIR."
# Validate for another user
THETARGET="$TARGET"
if [ ! -z "$THEUSER" ]
then
THETARGET=`eval echo "~$THEUSER/dbwebb-kurser/$COURSE"`
fi
for dir in $DIR; do
assert 0 "[ -d $THETARGET/$dir ]" "Missing directory: $THETARGET/$dir" || return
validateHtmlCssJs "$dir" "silent" "$THETARGET"
validatePython "$dir" "silent" "$THETARGET"
done
}
#
# Init the build directory
#
initBuildDir()
{
SILENT="$1"
if [ -z "$SILENT" ]; then
$ECHO "\nChecking the www directory."
fi
ME="$BUILD/me"
for dir in $BUILD1 $BUILD2 $BUILD3 $BUILD $ME $ME/kmom01 $ME/kmom02 $ME/kmom03 $ME/kmom04 $ME/kmom05 $ME/kmom06 $ME/kmom10; do
if [ ! -d $dir ]; then mkdir $dir; fi
done
}
#
# Publish all
#
publishChmod()
{
DIR="$1"
#find $BUILD/$dir/ -type d -print0 | xargs -0 chmod 755
#find $BUILD/$dir/ -type f -print0 | xargs -0 chmod 644
#find $BUILD/$dir/ -type f -name '*.cgi' -print0 | xargs -0 chmod 755
#find $BUILD/$dir/ -type f -name '*.py' -print0 | xargs -0 chmod 600
for filename in $(find "$DIR" -type d); do
chmod 755 "$filename"
done
for filename in $(find "$DIR" -type f); do
chmod 644 "$filename"
done
for filename in $(find "$DIR" -type f -name '*.cgi'); do
chmod 755 "$filename"
done
for filename in $(find "$DIR" -type f -name '*.py'); do
chmod 600 "$filename"
done
}
#
# Publish all
#
publish()
{
DIR="$1"
SILENT="$2"
if [ -z "$SILENT" ]; then
$ECHO "\n\nPublishing $DIR to www/$BASEDIR/$PROJECT."
fi
case "$DIR" in
example) DIRS="example" ;;
tutorial) DIRS="tutorial" ;;
me) DIRS="me" ;;
all) DIRS="example tutorial me" ;;
kmom*) DIRS="me/js me/style $DIR" ;;
*) DIRS="$DIR" ;;
esac
rsync -a --delete --exclude 'me/default' -f '- /*/' $TARGET/me/ $BUILD/me/
publishChmod "$BUILD/me/"
for filename in $(find $BUILD/me/ -maxdepth 1 -type f -name '*.html'); do
assert 0 "$HTML_MINIFIER $HTML_MINIFIER_OPTIONS $filename --output $filename" "HTMLMinifier failed: $filename"
done
for filename in $(find $BUILD/me/ -maxdepth 1 -type f -name '*.js'); do
assert 0 "$UGLIFYJS $filename -o $filename $UGLIFYJS_OPTIONS" "UglifyJS failed: $filename"
done
for filename in $(find $BUILD/me/ -maxdepth 1 -type f -name '*.css'); do
assert 0 "$CLEANCSS $filename -o $filename" "CleanCSS failed: $filename"
done
#find "$BUILD/me/" -maxdepth 1 -type f -name '*.html' | while read filename; do $HTML_MINIFIER $HTML_MINIFIER_OPTIONS $filename --output $filename; exit; done
#find "$BUILD/me/" -maxdepth 1 -type f -name '*.js' | while read filename; do $UGLIFYJS $filename -o $filename $UGLIFYJS_OPTIONS; done
#find "$BUILD/me/" -maxdepth 1 -type f -name '*.css' | while read filename; do $CLEANCSS $filename -o $filename; done
for dir in $DIRS; do
if [ ! -d "$TARGET/$dir" ]; then continue; fi
$ECHO "\n $dir:"
rsync -a --delete $TARGET/$dir/ $BUILD/$dir/
publishChmod "$BUILD/$dir/"
if [ -z "$SILENT" ]; then $ECHO " minify *.html"; fi
#find "$BUILD/$dir/" -type f -name '*.html' | while read filename; do assert "0" "$HTML_MINIFIER $HTML_MINIFIER_OPTIONS $filename --output $filename" "HTMLMinifier failed: $filename"; done
for filename in $(find "$BUILD/$dir/" -type f -name '*.html'); do
assert 0 "$HTML_MINIFIER $HTML_MINIFIER_OPTIONS $filename --output $filename" "HTMLMinifier failed: $filename"
done
if [ -z "$SILENT" ]; then $ECHO " uglify *.js"; fi
#$UGLIFYJS $BUILD/$KMOM/$DIR/js/main.js -o $BUILD/$KMOM/$DIR/js/main.js $UGLIFYJS_OPTIONS
#find "$BUILD/$dir/" -type f -name '*.js' | while read filename; do assert "0" "$UGLIFYJS $filename -o $filename $UGLIFYJS_OPTIONS" "UglifyJS failed: $filename"; done
for filename in $(find "$BUILD/$dir/" -type f -name '*.js'); do
assert 0 "$UGLIFYJS $filename -o $filename $UGLIFYJS_OPTIONS" "UglifyJS failed: $filename"
done
if [ -z "$SILENT" ]; then $ECHO " minify *.css"; fi
#$CLEANCSS $BUILD/$KMOM/$DIR/style/style.css -o $BUILD/$KMOM/$DIR/style/style.css
#find "$BUILD/$dir/" -type f -name '*.css' | while read filename; do assert "0" "$CLEANCSS $filename -o $filename" "CleanCSS failed: $filename"; done
for filename in $(find "$BUILD/$dir/" -type f -name '*.css'); do
assert 0 "$CLEANCSS $filename -o $filename" "CleanCSS failed: $filename"
done
done
}
#
# Main
#
if [ $# != 3 ]
then
:
#$ECHO
#printUsage
fi
# Get settings from config-file
. "./.dbwebb.config"
# Get options
OPT_CHMOD="yes"
OPT_CHECK="yes"
OPT_ME="yes"
SILENT="no"
PUBLISH="yes"
IGNORE_FAULTS="no"
while getopts ":hinrvmesut" opt
do
case $opt in
(h)
printUsage
exit 0
;;
(i)
IGNORE_FAULTS="yes"
;;
(n)
PUBLISH="no"
;;
(m)
OPT_CHMOD="no"
;;
(e)
OPT_CHECK="no"
;;
(t)
OPT_ME="no"
;;
#(u)
# THEUSER="$OPTARG"
# shift
# ;;
(r)
$ECHO "\nRequired external tools are:"
$ECHO "\n npm install jshint html-minifier uglify-js clean-css htmlhint pylint"
$ECHO "\n"
$ECHO "\n"
exit 0
;;
(s)
SILENT="yes"
;;
(v)
$ECHO "$VERSION\n"
exit 0
;;
\?)
$ECHO "\nInvalid option: -$OPTARG" >&2
$ECHO "\n"
$ECHO "\nUse the following to get help."
$ECHO "\ndbwebb-validate -h"
$ECHO "\n"
$ECHO "\n"
exit 1
;;
esac
done
shift $((OPTIND - 1))
# Get path to dir to check
FAULTS=0
CMD=$1
THEUSER=$2
DIR=$(mapCmdToDir "$CMD")
if [ $? -eq 1 ]; then
$ECHO "$DIR"
exit 1
fi
# Execute command
if [ $OPT_CHECK = "yes" ]; then checkTools; fi
if [ $OPT_CHMOD = "yes" ]; then setChmod; fi
if [ $OPT_CHMOD = "yes" ]; then testMe "$CMD"; fi
validate "$DIR"
if [ $PUBLISH = "yes" ]; then
initBuildDir "silent"
publish "$DIR"
fi
# Clean up and output results
rm -f $TMPFILE
if [ $FAULTS -gt 0 ]
then
if [ $IGNORE_FAULTS = "yes" ]
then
$ECHO "\n\n$MSG_WARNING"
STATUS=2
else
$ECHO "\n\n$MSG_FAILED"
STATUS=1
fi
$ECHO " Tests: $TESTS Asserts: $ASSERTS Faults: $FAULTS\n"
exit $STATUS
fi
$ECHO "\n\n$MSG_OK"
$ECHO " Tests: $TESTS Asserts: $ASSERTS Faults: $FAULTS\n"
exit 0