ads1_2021/scripts/.lib.sh

300 lines
9.0 KiB
Bash

#!/usr/bin/env bash
##############################################################################
# DESCRIPTION: Library of methods specifically for the project.
# Include using source .whales/.lib.sh
##############################################################################
source scripts/.lib.globals.sh;
source scripts/.lib.utils.sh;
##############################################################################
# GLOBAL VARIABLES
##############################################################################
env_from ".env" import REQUIREMENTS_GO as PATH_REQ_GO;
env_from ".env" import REQUIREMENTS_PY as PATH_REQ_PY;
env_from ".env" import NAME_OF_APP;
env_from ".env" import TEST_TIMEOUT;
export CONFIGENV="data/.env";
export PATH_PROJECT_PY="code/python";
export PATH_PROJECT_GO="code/golang";
export PATH_GO_ASSETS_GRAMMAR="assets/grammars";
export PATH_GO_INTERNAL_GRAMMAR="internal/tokenisers/grammars";
export PYTHON_APP_PREFIX=\
'''#!/usr/bin/env python3
# -*- coding: utf-8 -*-'''
export USE_VENV=false;
export UNITTEST_SCHEMA_PY="test_*.py";
##############################################################################
# AUXILIARY METHODS: Zip
##############################################################################
function create_zip_archive() {
zip -r $@;
}
##############################################################################
# AUXILIARY METHODS: Go
##############################################################################
function call_go() {
go $@;
}
function install_requirements_go() {
local path="$1";
local cwd="$PWD";
local has_problems=false;
local problem_packages=();
pushd $PATH_PROJECT_GO >> $VERBOSE;
# go mod tidy; # <- use to detect unused packages in project
remove_file "go.sum";
_log_info "Add go requirements";
dos_to_unix "$cwd/$path";
local line;
while read line; do
line="$( _trim_trailing_comments "$line" )";
[ "$line" == "" ] && continue;
_log_info "Run \033[92;1mGO GET\033[0m to install \033[93;1m$line\033[0m.";
( call_go get "$line" 2> $VERBOSE ) && continue;
has_problems=true;
problem_packages+=( "$line" );
done <<< "$( cat "$cwd/$path" )";
popd >> $VERBOSE
( $has_problems ) && _log_fail "Something went wrong whilst using \033[92;1mGO\033[0m to install: {\033[93;1m${problem_packages[*]}\033[0m}.";
}
function compile_go() {
local force="$1";
local path="$2";
local cwd="$PWD";
_log_info "Compile \033[1mmain.go\033[0m with \033[1mgolang\033[0m";
remove_file "dist/$NAME_OF_APP";
pushd "$path" >> $VERBOSE;
call_go build -o "$cwd/dist/$NAME_OF_APP" "main.go";
popd >> $VERBOSE;
! [ -f "dist/$NAME_OF_APP" ] && return 1;
return 0;
}
##############################################################################
# AUXILIARY METHODS: Python
##############################################################################
function use_python_venv_true() { USE_VENV=true; }
function use_python_venv_false() { USE_VENV=false; }
function create_python_venv() {
! ( $USE_VENV ) && return;
_log_info "Create VENV";
! [ -d build ] && mkdir build;
pushd build >> $VERBOSE;
call_python -m venv env;
popd >> $VERBOSE;
}
function activate_python_venv() {
! ( $USE_VENV ) && return;
if ( is_linux ); then
source build/env/bin/activate;
else
source build/env/Scripts/activate;
fi
}
function deactivate_python_venv() {
! ( $USE_VENV ) && return;
if ( is_linux ); then
source build/env/bin/deactivate;
else
source build/env/Scripts/deactivate;
fi
}
function call_python() {
if ( is_linux ); then
python3 $@;
else
py -3 $@;
fi
}
function call_v_python() { activate_python_venv && call_python $@; }
function call_utest() { call_python -m unittest discover $@; }
function call_v_utest() { activate_python_venv && call_utest $@; }
function call_pipinstall() {
# Do not use --user flag with venv
DISPLAY= && call_python -m pip install $@;
}
function install_requirements_python() {
local path="$1";
local has_problems=false;
local problem_packages=();
dos_to_unix "$path";
local line;
while read line; do
line="$( _trim_trailing_comments "$line" )";
[ "$line" == "" ] && continue;
_log_info "Run \033[92;1mPIP\033[0m to install \033[93;1m$line\033[0m.";
( call_pipinstall "$line" >> $VERBOSE ) && continue;
has_problems=true;
problem_packages+=( "$line" );
done <<< "$( cat "$path" )";
( $has_problems ) && _log_fail "Something went wrong whilst using \033[92;1mPIP\033[0m to install: {\033[93;1m${problem_packages[*]}\033[0m}.";
}
function install_requirements_v_python() { activate_python_venv && install_requirements_python $@; }
##############################################################################
# AUXILIARY METHODS: CLEANING
##############################################################################
function garbage_collection_misc() {
clean_all_folders_of_pattern ".DS_Store";
}
function garbage_collection_python() {
clean_folder_contents "$PATH_PROJECT_PY/build";
local path;
for path in "$PATH_PROJECT_PY"; do
pushd "$path" >> $VERBOSE;
# clean_all_files_of_pattern "*\.pyo";
clean_all_folders_of_pattern "__pycache__";
popd >> $VERBOSE;
done
}
function garbage_collection_go {
_log_info "(There are no go files to clean.)";
}
function garbage_collection_dist() {
remove_file "dist/$NAME_OF_APP";
}
##############################################################################
# MAIN METHODS: PROCESSES
##############################################################################
function run_setup() {
_log_info "RUN SETUP";
local current_dir="$PWD";
pushd $PATH_PROJECT_PY >> $VERBOSE;
create_python_venv;
_log_info "Check and install missing requirements";
install_requirements_v_python "$current_dir/$PATH_REQ_PY";
popd >> $VERBOSE;
}
function run_setup_go() {
install_requirements_go "$PATH_REQ_GO";
}
function run_create_artefact() {
local current_dir="$PWD";
local success;
## create temp artefacts:
local _temp="$( create_temporary_dir "dist" )";
mkdir "$_temp/src"
cp -r "$PATH_PROJECT_PY/src/." "$_temp/src";
copy_file file="VERSION" from="dist" to="${_temp}/src/setup";
mv "${_temp}/src/__main__.py" "$_temp";
## zip source files to single file and make executable:
pushd "$_temp" >> $VERBOSE;
( create_zip_archive -o "$current_dir/dist/app.zip" * -x '*__pycache__/*' -x '*.DS_Store' );
success=$?
popd >> $VERBOSE;
if [ $success -eq 0 ]; then
echo "$PYTHON_APP_PREFIX" | cat - dist/app.zip > dist/$NAME_OF_APP;
chmod +x "dist/$NAME_OF_APP";
fi
## remove temp artefacts:
remove_dir "$_temp";
remove_file "dist/app.zip";
! [ $success -eq 0 ] && return 1;
_log_info "Python artefact successfully created.";
return 0;
}
function run_create_artefact_go() {
local current_dir="$PWD";
local success;
## create temp artefacts:
local _temp="$( create_temporary_dir "dist" )";
cp -r "$PATH_PROJECT_GO/." "$_temp";
copy_file file="VERSION" from="dist" to="${_temp}/assets";
( compile_go true "$_temp" );
success=$?;
## remove temp artefacts:
remove_dir "$_temp";
! [ $success -eq 0 ] && return 1;
return 0;
}
function run_main() {
pushd $PATH_PROJECT_PY >> $VERBOSE;
call_v_python src/main.py $@;
popd >> $VERBOSE;
}
function run_main_go() {
compile_go false "$PATH_PROJECT_GO";
./dist/$NAME_OF_APP $@;
}
function run_test_unit() {
local asverbose=$1;
local verboseoption="-v";
local success=0;
! ( $asverbose ) && verboseoption="";
_log_info "RUN UNITTESTS";
pushd $PATH_PROJECT_PY >> $VERBOSE;
( call_v_utest \
$verboseoption \
--top-level-directory "test" \
--start-directory "test" \
--pattern "${UNITTEST_SCHEMA_PY}" 2>&1 \
);
success=$?;
popd >> $VERBOSE;
[ $success -eq 1 ] && _log_fail "Unit tests failed!";
_log_info "Unit tests successful!";
return 0;
}
function run_test_unit_go() {
local asverbose="$1";
local verboseoption="-v";
local success;
_log_info "RUN UNITTESTS";
! ( $asverbose ) && verboseoption=""
pushd $PATH_PROJECT_GO >> $VERBOSE;
( call_go test $verboseoption -timeout $TEST_TIMEOUT -count 1 -run "^Test[A-Z].*" "$NAME_OF_APP" "./..." );
success=$?;
popd >> $VERBOSE
[ $success -eq 1 ] && _log_fail "Unit tests failed!";
_log_info "Unit tests successful!";
return 0;
}
function run_clean_artefacts() {
_log_info "CLEAN ARTEFACTS";
garbage_collection_misc;
garbage_collection_python;
garbage_collection_go;
garbage_collection_dist;
}