#!/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 $@