shell-base/modules/scripting/bundle.func

120 lines
3.7 KiB
Bash

#!/bin/bash
# $1 file to bundle
# $2 bundled output file (optional)
# if no output file then the bundled source is returned
# it can be immediately invoked like this
# source <(bundle myscript.sh)
# or
# scpt=$(bundle myscript.sh)
# source <(echo -e "$scpt")
module_load debug
module_load file
module_load helpers
# TODO keep debug statements if requested, other remove them
bundle () {
local file; local xfunc; local compact; local func;
debug $( ( IFS=$','; echo bundle arguments: "$*" ) )
declare OPTION; declare OPTARG; declare OPTIND
while getopts 'cf:x:' OPTION; do
case "$OPTION" in
c)
compact=true
;;
f)
# can pass any arguments along with the function to run. Use " " for any argument with spaces
func="$OPTARG"
;;
x)
# will extract a function from a file or module to be used for bundling
xfunc="$OPTARG"
;;
*)
echo unknown bundle option $OPTION
;;
esac
done
shift $(( OPTIND - 1 ))
tmp_file=$( mktemp -t TEMP_FILE_bundle.XXXXXXXX )
chmod 600 "$tmp_file"
if [[ -f $1 ]]; then file=$1; else
if ! file=$(module_find "$1"); then >&2 echo fatal: bundle error, no module of name: $1; file=""; fi; fi
[[ ! $file ]] && >&2 echo "fatal: bundle error aborting, no file, module passed for bundling" && return 1
\cp $file $tmp_file
if [[ $xfunc ]]; then
( source $file; declare -f $xfunc > $tmp_file )
fi
if [[ ! $2 == "__recurse__" ]]; then
_modules=""
output=$2
[[ $output ]] && debug outputing bundle to: $output || debug outputting bundle to console
debug "bash code to bundle \n $(cat $tmp_file)"
fi
modules=$(sed -n -e 's/^\s*module_load //p' < $tmp_file)
# if [[ ( ! $modules ) && ( ! $2 == "__recurse__" ) ]]; then
# if [[ $output ]]; then
# \cp $tmp_file $output
# else
# echo -e "$(cat $tmp_file)"
# fi
# fi
# remove debug module by default so it doesn't get bundled
if [[ $modules ]]; then
# remove all found module_load before continuing
sed -i '/^\s*module_load/d' $tmp_file
[[ $_modules ]] && debug "already bundled modules: $_modules"
for module in $(printf '%s\n' "${modules[@]}"|tac);
do
if [[ $_modules == " $module "* ]]; then
[[ $_modules ]] && debug module $module already bundled
else
if modp=$(module_find ${module}); then
debug bundling module ${module} at: $modp
prepend_file $modp $tmp_file
fi
fi
done
_modules="$_modules $modules"
bundle $tmp_file __recurse__
fi
# the recursion is done
if [[ ! $2 == "__recurse__" ]]; then
[[ $compact ]] && compact_file $tmp_file
# TODO remove debug statements by default
# remove any default function calls
sed -i '/\s*(\s*return 0 2>\/dev\/null\s*)\s*|| /d' $tmp_file
# add in a function call if requested
[[ $func ]] && echo -e "\n $func \"\$@\"" >> $tmp_file
if [[ $BASH_DEBUG ]]; then
debug "\n ------------code as bundled--------------\n \
$(cat $tmp_file) \
\n ------------------------------------------------------------ \n"
debug "bundled modules were $_modules"
fi
if [[ $output ]]; then
\cp $tmp_file $output
else
echo -e "$(cat $tmp_file)"
fi
rm -f $tmp_file;
return 0
fi
}
# # if script was executed then call the function
(return 0 2>/dev/null) || bundle $@