mirror of
https://github.com/Pmodules/Pmodules.git
synced 2026-06-26 01:23:09 +02:00
748 lines
20 KiB
Plaintext
Executable File
748 lines
20 KiB
Plaintext
Executable File
#!@BASH@ --noprofile
|
|
|
|
PATH='/bin:/usr/bin'
|
|
unset CDPATH # unset CDPATH, otherwise 'cd' prints the directoy!
|
|
unset IFS # use default IFS
|
|
|
|
shopt -s nullglob
|
|
shopt -s extglob
|
|
|
|
# used for some output only
|
|
declare -r CMD='modmanage'
|
|
|
|
declare mydir=$(cd $(dirname "$0") && pwd)
|
|
declare prefix=$(dirname "${mydir}")
|
|
declare libdir="${prefix}/lib"
|
|
declare libexecdir="${prefix}/libexec"
|
|
declare -r bindir="${prefix}/bin"
|
|
|
|
source "${libdir}/libstd.bash"
|
|
source "${libdir}/libpmodules.bash"
|
|
|
|
_exit () {
|
|
std::die 1 "\nInterrupted..."
|
|
}
|
|
trap '_exit' INT TERM
|
|
|
|
_err () {
|
|
std::info "\nOops: got an error in function '${FUNCNAME[1]}', line ${BASH_LINENO[0]}"
|
|
std::die 1 "Aborting ..."
|
|
}
|
|
trap '_err' ERR
|
|
|
|
path="/bin:/usr/bin:${bindir}"
|
|
[[ $(uname -s) == 'Darwin' ]] && path+=":${libexecdir}"
|
|
std::def_cmds "${path}" 'chown' 'dirname' 'mkdir' 'rsync' 'rm' 'getopt' 'find' 'modulecmd'
|
|
|
|
unset mydir
|
|
unset prefix
|
|
unset libdir
|
|
unset libexecdir
|
|
# bindir we still need
|
|
|
|
declare PMODULES_VERSION='@PMODULES_VERSION@'
|
|
|
|
##############################################################################
|
|
#
|
|
# help [module|sub-command]
|
|
#
|
|
Subcommands[help]='help'
|
|
Options[help]='-o hHV\? -l version -l help'
|
|
Help[help]='
|
|
USAGE:
|
|
modmanage [switches] subcommand [subcommand-args]...
|
|
|
|
SWITCHES:
|
|
-h|-H|-?|--help this usage info
|
|
-V|--version modules version & configuration options
|
|
--debug enable debug output
|
|
--dry-run dry run
|
|
|
|
SUBCOMMANDS:
|
|
+ init [switches] TARGET_DIR
|
|
+ install [switches] module...
|
|
+ search [switches] [string|pattern]...
|
|
+ help [subcommand]
|
|
'
|
|
|
|
subcommand_help() {
|
|
local -r subcommand='help'
|
|
local -a args=()
|
|
while (( $# > 0 )); do
|
|
case $1 in
|
|
-h | -\? | -H | --help )
|
|
print_help "${subcommand}"
|
|
;;
|
|
-V | --version )
|
|
print_help 'version'
|
|
;;
|
|
-- )
|
|
shift 1
|
|
args+=( "$@" )
|
|
break
|
|
;;
|
|
* )
|
|
args+=( "$1" )
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
for arg in "${args[@]}"; do
|
|
if [[ -n "${Help[${arg}]}" ]] ; then
|
|
print_help "${arg}"
|
|
else
|
|
std::die 1 "Unknown sub-command -- ${subcommand}"
|
|
fi
|
|
done
|
|
}
|
|
|
|
##############################################################################
|
|
#
|
|
# Derive the module installation path from the modulefile path.
|
|
# The passed modulefile must be absolute.
|
|
#
|
|
# Arguments:
|
|
# $1: absolute module file path
|
|
#
|
|
get_module_prefix() {
|
|
"${modulecmd}" bash show "$1" 2>&1 \
|
|
|awk '/_HOME |_PREFIX / {print $3; exit}'
|
|
}
|
|
|
|
##############################################################################
|
|
#
|
|
# Derive the module release-file path from the module file-path.
|
|
#
|
|
# Arguments:
|
|
# $1: module file-path
|
|
#
|
|
get_releasefile_name() {
|
|
echo "$(${dirname} "$1")/.release-$(basename "$1")"
|
|
}
|
|
|
|
##############################################################################
|
|
#
|
|
# Sync a module from one Pmodules environment to another:
|
|
# - sync module installation
|
|
# - sync modulefile
|
|
# - sync release file
|
|
#
|
|
# Arguments:
|
|
# $1: relative modulefile path (something like: Tools/gnuplot/5.0.0)
|
|
# $2: source prefix of Pmodule environment
|
|
# $3: target prefix of Pmodule environment
|
|
#
|
|
sync_module() {
|
|
local -r rel_modulefile="$1"
|
|
local -r src_root="$2"
|
|
local -r target_root="$3"
|
|
|
|
local -r src_prefix=$( get_module_prefix "${src_root}/${rel_modulefile}" )
|
|
local -r rel_prefix=${src_prefix#${src_root}/}
|
|
local -r target_prefix="${target_root}/${rel_prefix}"
|
|
|
|
# install/update module
|
|
if [[ ! -d "${target_prefix}" ]] || [[ "${force}" == 'yes' ]]; then
|
|
${mkdir} -p "${target_prefix}" || exit $?
|
|
${rsync} --links --perms --recursive --delete \
|
|
"${src_prefix}/" \
|
|
"${target_prefix}/" || exit $?
|
|
fi
|
|
|
|
# create modulefile direcrory and install modulefile
|
|
local -r src_modulefile="${src_root}/${rel_modulefile}"
|
|
local -r target_modulefile="${target_root}/${rel_modulefile}"
|
|
|
|
${mkdir} -p "$(${dirname} "${target_modulefile}")" || exit $?
|
|
|
|
if [[ -e "${src_modulefile}" ]]; then
|
|
${rsync} --links --perms --recursive \
|
|
"${src_modulefile}" "${target_modulefile}" || exit $?
|
|
fi
|
|
|
|
# install release-file
|
|
local -r rel_releasefile=$( get_releasefile_name "${rel_modulefile}" )
|
|
local -r src_releasefile="${src_root}/${rel_releasefile}"
|
|
local -r target_releasefile="${target_root}/${rel_releasefile}"
|
|
|
|
if [[ -e "${src_releasefile}" ]]; then
|
|
${rsync} --links --perms --recursive \
|
|
"${src_releasefile}" "${target_releasefile}" || exit $?
|
|
fi
|
|
|
|
}
|
|
|
|
##############################################################################
|
|
#
|
|
# initialize a new module environment
|
|
#
|
|
#
|
|
#
|
|
Subcommands[init]='init'
|
|
Options[init]='-o \?hfy -l src: -l user: -l help -l force -l yes'
|
|
Help[init]="
|
|
USAGE:
|
|
modmanage init [switches] TARGET_DIR
|
|
Initialize a new minimal Pmodule environment in TARGET_DIR.
|
|
A user must be specified with '--user=<USER>' if the
|
|
programm is executed as root.
|
|
|
|
SWITCHES:
|
|
--user <USER>
|
|
If this scripts runs with root privileges, a user name
|
|
ore ID must be specified.
|
|
--force|--yes|-f|-y
|
|
re-initialise an already existing Pmodule environment.
|
|
"
|
|
|
|
subcommand_init() {
|
|
check_env() {
|
|
[[ -n "${PMODULES_ROOT}" ]] &&
|
|
[[ -d "${PMODULES_ROOT}" ]] &&
|
|
[[ -n "${PMODULES_HOME}" ]] &&
|
|
[[ -n "${PMODULES_VERSION}" ]] || \
|
|
std::die 1 "
|
|
Error: the module environment you are going to use as source has not been
|
|
initialized properly!"
|
|
}
|
|
|
|
#.....................................................................
|
|
#
|
|
# Sync the Pmodules configuration and templates
|
|
#
|
|
# Arguments:
|
|
# $1: source prefix of Pmodule environment
|
|
# $2: target prefix of Pmodule environment
|
|
#
|
|
sync_config() {
|
|
src="$1/${PMODULES_CONFIG_DIR}/"
|
|
dst="$2/${PMODULES_CONFIG_DIR}/"
|
|
${rsync} --links --perms \
|
|
"${src}"/profile.{bash,csh,zsh} "${dst}" \
|
|
|| return $?
|
|
${rsync} --links --perms \
|
|
"${src}"/profile.{bash,csh,zsh}-"${PMODULES_VERSION}" "${dst}" \
|
|
|| return $?
|
|
${rsync} --links --perms \
|
|
"${src}/Pmodules.conf" "${dst}" \
|
|
|| return $?
|
|
${rsync} --links --perms \
|
|
"${src}/modbuild.conf" "${dst}" \
|
|
|| return $?
|
|
}
|
|
|
|
local target_root=()
|
|
local user=''
|
|
while (($# > 0)); do
|
|
case $1 in
|
|
-h | -H | -\? | --help | -help )
|
|
print_help "${subcommand}"
|
|
;;
|
|
--force | --yes | -f | -y )
|
|
force='yes'
|
|
;;
|
|
--user | --user=* )
|
|
if [[ "$1" == '--user' ]]; then
|
|
user="$2"
|
|
shift
|
|
else
|
|
user="${1#--*=}"
|
|
fi
|
|
;;
|
|
-- )
|
|
:
|
|
;;
|
|
* )
|
|
# assign and remove trailing slashes
|
|
target_root="${1%%*([\/])}"
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
if [[ -z ${target_root} ]]; then
|
|
std::die 1 "Error: no target directory specified!"
|
|
fi
|
|
|
|
local -i euid=$(id -u)
|
|
if (( euid == 0 )); then
|
|
[[ -n "${user}" ]] || \
|
|
std::die 1 "Error: --user parameter is required!"
|
|
id -u "${user}" > /dev/null 2>&1 || \
|
|
std::die 1 "Error: Unable to retrieve user id of user '${user}'"
|
|
else
|
|
[[ -z "${user}" ]] || \
|
|
std::die 1 "Error: --user option is only allowed if running as root!"
|
|
fi
|
|
|
|
local src_root="$(std::get_abspath "${bindir}/../../../..")"
|
|
local config_file="${src_root}/${PMODULES_CONFIG_DIR}/profile.bash"
|
|
if [[ -r "${config_file}" ]]; then
|
|
source "${config_file}"
|
|
fi
|
|
check_env || \
|
|
std::die 1 "Giving up..."
|
|
|
|
echo "Creating a minimal Pmodule environment from the environment at"
|
|
echo " ${PMODULES_ROOT}"
|
|
echo "in"
|
|
echo " ${target_root}"
|
|
if [[ -d "${target_root}" ]] && [[ ${force} == no ]]; then
|
|
echo "Warning: ${target_root} already exists."
|
|
std::get_YN_answer \
|
|
"Do you really want to re-run the initialization? (y/N) " \
|
|
|| std::die 1 "Abort ..."
|
|
fi
|
|
force='yes'
|
|
echo "Creating target directory '${target_root}'..."
|
|
${mkdir} -p "${target_root}" || \
|
|
std::die 1 "Error: make directory failed!"
|
|
|
|
echo "Syncing configuration ..."
|
|
sync_config "${src_root}" \
|
|
"${target_root}" || \
|
|
std::die 1 "Error: configuration synchronization failed!"
|
|
|
|
echo "Syncing Pmodules ${PMODULES_VERSION} from '${src_root}' to '${target_root}'..."
|
|
sync_module "Tools/${PMODULES_MODULEFILES_DIR}/Pmodules/${PMODULES_VERSION}" \
|
|
"${src_root}" \
|
|
"${target_root}" || \
|
|
std::die 1 "Error: sync Pmodules failed!"
|
|
|
|
for d in "${src_root}"/*/${PMODULES_MODULEFILES_DIR}; do
|
|
${mkdir} -p "${target_root}/${d#${src_root}/}"
|
|
done
|
|
|
|
if [[ -n "${user}" ]]; then
|
|
echo "Changing user of new module environment to '${user}'..."
|
|
${chown} -R "${user}" "${target_root}" || \
|
|
std::die 1 "Error: changing owner failed!"
|
|
echo
|
|
fi
|
|
echo "SourceRoot=${src_root}" > "${target_root}/${PMODULES_CONFIG_DIR}/modmanage.conf"
|
|
echo "New minimal module environment created at '${target_root}'."
|
|
echo "To use this environment, execute"
|
|
echo " sudo ln -fs ${target_root} /opt/psi"
|
|
echo " source /opt/psi/${PMODULES_CONFIG_DIR}/profile.bash"
|
|
|
|
}
|
|
|
|
|
|
##############################################################################
|
|
#
|
|
# sub-command 'install'
|
|
#
|
|
# Arguments:
|
|
Subcommands[install]='install'
|
|
Options[install]='-o hf -l force -l with: -l help -l src: -l target:'
|
|
Help[install]='
|
|
USAGE:
|
|
modmanage install [switches] <module>...
|
|
Install modules
|
|
|
|
SWITCHES:
|
|
--force] | -f
|
|
Install module even it already exists
|
|
|
|
--src <src>
|
|
Install from module environment in <src>
|
|
|
|
--with <module>
|
|
Install module(s) in this sub-group only
|
|
|
|
<module_pattern>
|
|
Install modules matching given pattern
|
|
'
|
|
|
|
subcommand_install() {
|
|
local -r subcommand='install'
|
|
local opts=''
|
|
local -a with=()
|
|
local -a module_pattern=()
|
|
local src_root="${PMODULES_INSTALL_SOURCE}"
|
|
local target_root="${PMODULES_ROOT}"
|
|
local modulefile=''
|
|
local -A modules_to_install
|
|
local -A dependencies_to_install
|
|
local -A group_map
|
|
local -a modulepath=()
|
|
|
|
#......................................................................
|
|
#
|
|
set_initial_modulepath() {
|
|
local group
|
|
for group in "${!GroupDepths[@]}"; do
|
|
(( ${GroupDepths[${group}]} == 0 )) || continue
|
|
modulepath+=( "${src_root}/${group}/${PMODULES_MODULEFILES_DIR}" )
|
|
done
|
|
}
|
|
|
|
#......................................................................
|
|
#
|
|
create_group_map() {
|
|
#
|
|
# For the dependency resolution we need to know, whether a
|
|
# module - if loaded - adds a hierarchical group to MODULEPATH
|
|
# or not.
|
|
#
|
|
# Examples:
|
|
# Loading a compiler adds the hierarchical group for
|
|
# this compiler. The command
|
|
# module load gcc/10.3.0
|
|
# prepends
|
|
# <pmodules_root>/Compiler/modulefiles/gcc/10.3.0
|
|
# to MODULEPATH.
|
|
#
|
|
# The dependency files do not convey the information whether
|
|
# loading a module extends MODULEPATH or not. What we need to
|
|
# know is
|
|
# 1) does loading a specific module extends MODULEPATH?
|
|
# 2) if yes: what is the hierarchical group?
|
|
#
|
|
# Example:
|
|
# If we know that loading 'gcc/10.3.0' adds a directory
|
|
# in the hierarchical group 'Compiler' to MODULEPATH, we
|
|
# know that this directory is
|
|
# <pmodules_root>/Compiler/modulefiles/gcc/10.3.0
|
|
#
|
|
# This information we store in the dictionary 'group_map'.
|
|
# For concinience reasons we store the string 'src_root/group'.
|
|
# So, 'group_map' maps
|
|
# module/version -> src_root/group
|
|
#
|
|
# Example:
|
|
# group_map[gcc/10.3.0]="${src_root}/Compiler"
|
|
#
|
|
local group=''
|
|
for group in "${!GroupDepths[@]}"; do
|
|
(( ${GroupDepths[${group}]} > 0 )) || continue
|
|
local fname=''
|
|
while read fname; do
|
|
local -a parts=()
|
|
std::split_relpath parts "${fname}"
|
|
if (( ${#parts[@]} - 2 != ${GroupDepths[${group}]} )); then
|
|
std::warn "error in source group ${group}:"
|
|
std::warn "modulefile: ${fname}"
|
|
continue
|
|
fi
|
|
if [[ ${#parts[@]} < 4 ]]; then
|
|
echo "${group} ${parts[@]}"
|
|
fi
|
|
local key="${parts[-4]}/${parts[-3]}"
|
|
[[ -z "${group_map[${key}]}" ]] || continue
|
|
group_map[${key}]="${src_root}/${group}"
|
|
done < <(${find} -L "${src_root}/${group}/${PMODULES_MODULEFILES_DIR}" \
|
|
\( -type l -o -type f \) \
|
|
\! -name ".*" \
|
|
-printf "%P\n" \
|
|
)
|
|
done
|
|
}
|
|
|
|
#......................................................................
|
|
#
|
|
# Resolve dependencies to given module
|
|
#
|
|
# Arguments:
|
|
# $1 absolute module file name
|
|
#
|
|
# Notes:
|
|
# Following variables from the enclosing function are used:
|
|
# modulepath
|
|
# group_map (read-only)
|
|
#
|
|
resolve_dependencies () {
|
|
local -r modulefile="$1"
|
|
|
|
local -- prefix=$(get_module_prefix "${modulefile}")
|
|
local -a rdeps=()
|
|
local -- rdeps_file="${prefix}/.dependencies"
|
|
local -a ideps=()
|
|
local -- ideps_file="${prefix}/.install_dependencies"
|
|
|
|
if [[ -r "${rdeps_file}" ]]; then
|
|
mapfile -t rdeps < <(grep -v '^ *#' "${rdeps_file}" )
|
|
fi
|
|
if [[ -r "${ideps_file}" ]]; then
|
|
mapfile -t ideps < <(grep -v '^ *#' "${ideps_file}" )
|
|
fi
|
|
|
|
# loop over all dependecies
|
|
local dep
|
|
for dep in "${rdeps[@]}" "${ideps}"; do
|
|
[[ -n ${dep} ]] || continue
|
|
# search module with current modulepath
|
|
local modulename=$(${find} "${modulepath[@]}" -path "*/${dep}" \
|
|
-print -quit 2>/dev/null)
|
|
[[ -n ${modulename} ]] || \
|
|
std::die 3 "Oops: required module '${dep}' not found!"
|
|
|
|
local rel_modulename="${modulename#${src_root}/}"
|
|
dependencies_to_install[${rel_modulename}]='.'
|
|
resolve_dependencies "${modulename}"
|
|
[[ -v group_map[${dep}] ]] || continue
|
|
local dir="${group_map[${dep}]}" # = ${src_root}/<group>
|
|
dir+="/${rel_modulename##+([!/])/}" # += rel.name with group removed
|
|
modulepath+=( "${dir}" )
|
|
done
|
|
}
|
|
|
|
#......................................................................
|
|
#
|
|
# Print list of modules which will be installed and ask user wheter
|
|
# he wants to continue or abort.
|
|
#
|
|
# Arguments:
|
|
# none
|
|
#
|
|
# Notes:
|
|
# Following variables from the enclosing function are used:
|
|
# target_root (read-only)
|
|
# modules_to_install (read-only)
|
|
# dependencies_to_install (read-only)
|
|
#
|
|
print_modules() {
|
|
local modulefile
|
|
for modulefile in "$@"; do
|
|
local -a parts
|
|
std::split_relpath parts "${modulefile}"
|
|
local s=''
|
|
if (( ${#parts[@]} >= 6 )); then
|
|
s="(${parts[2]}/${parts[3]}"
|
|
for ((i = 4; i < ${#parts[@]}-2; i+=2)); do
|
|
s+=" ${parts[i]}/${parts[i+1]}"
|
|
done
|
|
s+=')'
|
|
fi
|
|
std::info "%-20s %s" "${parts[-2]}/${parts[-1]}" "$s"
|
|
done 2>&1 | sort
|
|
}
|
|
print_modules_to_install() {
|
|
std::info "The following modules will be installed/updated:"
|
|
print_modules "${!modules_to_install[@]}"
|
|
if (( ${#dependencies_to_install[@]} > 0 )); then
|
|
std::info "\nThe following dependencies will be installed/updated:"
|
|
print_modules "${!dependencies_to_install[@]}"
|
|
fi
|
|
std::info ""
|
|
std::get_YN_answer "Do you want to continue? [n] " || \
|
|
std::die 1 "Aborting..."
|
|
std::info ""
|
|
}
|
|
|
|
while (($# > 0)); do
|
|
case $1 in
|
|
-h | -H | -\? | --help | -help )
|
|
print_help "${subcommand}"
|
|
;;
|
|
--force | -f )
|
|
force='yes'
|
|
;;
|
|
--src | --src=*)
|
|
if [[ $1 == --src ]]; then
|
|
src_root="$2"
|
|
shift
|
|
else
|
|
src_root="${1#--*=}"
|
|
fi
|
|
;;
|
|
--target | --target=*)
|
|
if [[ $1 == --target ]]; then
|
|
target_root="$2"
|
|
shift
|
|
else
|
|
target_root="${1#--*=}"
|
|
fi
|
|
;;
|
|
--with | --with=* )
|
|
if [[ "$1" == --with ]]; then
|
|
with+=( "$2" )
|
|
shift
|
|
else
|
|
with+=( "${1#--*=}" )
|
|
fi
|
|
;;
|
|
-- )
|
|
:
|
|
;;
|
|
* )
|
|
module_pattern+=( "$1" )
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
if [[ -z ${src_root} ]]; then
|
|
local conf_file="${PMODULES_ROOT}/${PMODULES_CONFIG_DIR}/modmanage.conf"
|
|
if [[ -r ${conf_file} ]]; then
|
|
source "${conf_file}"
|
|
src_root="${SourceRoot}"
|
|
fi
|
|
fi
|
|
[[ -n ${src_root} ]] \
|
|
|| std::die 3 "Oops: no installation source given."
|
|
[[ -d ${src_root} ]] \
|
|
|| std::die 3 "Oops: '${src_root}' is not a valid installation source."
|
|
|
|
source "${src_root}/${PMODULES_CONFIG_DIR}/profile.bash"
|
|
scan_groups "${src_root}"
|
|
set_initial_modulepath
|
|
create_group_map
|
|
|
|
# search for to be installed modules and their dependencies
|
|
while read modulefile; do
|
|
modules_to_install["${modulefile#${src_root}/}"]+='.'
|
|
resolve_dependencies "${modulefile}"
|
|
done < <("${modulecmd}" bash search \
|
|
"${module_pattern[@]}" \
|
|
"${with[@]/#/--with=}" \
|
|
-a --glob \
|
|
--no-header --print-modulefiles \
|
|
--src="${src_root}" 2>&1 1>/dev/null)
|
|
(( ${#modules_to_install[@]} == 0 )) && \
|
|
std::die 0 "No matching modules found ..."
|
|
print_modules_to_install
|
|
|
|
# install/update ...
|
|
for modulefile in "${!modules_to_install[@]}" "${!dependencies_to_install[@]}"; do
|
|
std::split_relpath parts "${modulefile}"
|
|
std::info " ${parts[-2]}/${parts[-1]}"
|
|
sync_module "${modulefile}" "${src_root}" "${target_root}"
|
|
done
|
|
std::info "\nDone!\n"
|
|
} # subcommand_install
|
|
|
|
##############################################################################
|
|
#
|
|
# sub-command 'search'
|
|
#
|
|
Subcommands[search]='search'
|
|
Options[search]='-o \?h -l with: -l help -l all-dep -l wrap -l glob -l src:'
|
|
Help[install]='
|
|
USAGE:
|
|
modmanage search [switches] <string>...
|
|
search modules
|
|
|
|
SWITCHES:
|
|
--src <src>
|
|
Search modules in environment <src>.
|
|
Default is the source defined in modmanage.conf.
|
|
|
|
--with <module>
|
|
Search module(s) in this sub-group.
|
|
|
|
<string>
|
|
Search modules matching given string.
|
|
|
|
<pattern>
|
|
Search modules matching given shell glob-pattern.
|
|
'
|
|
|
|
subcommand_search() {
|
|
local -a args=()
|
|
while (($# > 0)); do
|
|
case $1 in
|
|
-h | -H | -\? | --help | -help )
|
|
print_help "${subcommand}"
|
|
;;
|
|
--src | --src=*)
|
|
if [[ $1 == --src ]]; then
|
|
src_root="$2"
|
|
shift
|
|
else
|
|
src_root="${1#--*=}"
|
|
fi
|
|
;;
|
|
--with | --with=* )
|
|
if [[ "$1" == --with ]]; then
|
|
args+=( '--with' "$2" )
|
|
shift
|
|
else
|
|
args+=( "$1" )
|
|
fi
|
|
;;
|
|
--all-deps | --glob | --wrap )
|
|
args+=( "$1" )
|
|
;;
|
|
-- )
|
|
:
|
|
;;
|
|
* )
|
|
args+=( "$1" )
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
if [[ -z ${src_root} ]]; then
|
|
local conf_file="${PMODULES_ROOT}/${PMODULES_CONFIG_DIR}/modmanage.conf"
|
|
if [[ -r ${conf_file} ]]; then
|
|
source "${conf_file}"
|
|
src_root="${SourceRoot}"
|
|
fi
|
|
fi
|
|
[[ -n ${src_root} ]] \
|
|
|| std::die 3 "Oops: no installation source given."
|
|
[[ -d ${src_root} ]] \
|
|
|| std::die 3 "Oops: '${src_root}' is not a valid installation source."
|
|
${modulecmd} bash search --src="${src_root}" --all-release-stages \
|
|
"${args[@]}" 2>&1 1>/dev/null
|
|
}
|
|
|
|
declare force='no'
|
|
declare subcommand=''
|
|
declare -a opts=()
|
|
while (($# > 0)); do
|
|
case $1 in
|
|
-h | -H | -\? | --help | -help )
|
|
print_help 'help'
|
|
;;
|
|
-V | --version )
|
|
print_help 'version'
|
|
;;
|
|
--debug )
|
|
set -x
|
|
;;
|
|
--dry-run )
|
|
chown="echo ${chown}"
|
|
mkdir="echo ${mkdir}"
|
|
rsync="echo ${rsync}"
|
|
;;
|
|
-* )
|
|
opts+=( "$1" )
|
|
;;
|
|
* )
|
|
subcommand="$1"
|
|
shift
|
|
break
|
|
;;
|
|
esac
|
|
shift || :
|
|
done
|
|
|
|
if [[ -z "${subcommand}" ]]; then
|
|
std::die 1 "${CMD}: no sub-command specified.\n"
|
|
print_help 'help'
|
|
fi
|
|
|
|
if [[ -z "${Subcommands[${subcommand}]}" ]]; then
|
|
std::die 1 "${CMD}: unknown sub-command -- ${subcommand}\n"
|
|
fi
|
|
|
|
if [[ "${subcommand}" != "init" ]] && [[ -z "${PMODULES_ROOT}" ]]; then
|
|
std::die 1 "Error: No current module environment configured!"
|
|
fi
|
|
|
|
tmp=$("${getopt}" --name="${CMD}" ${Options[${subcommand}]} -- "${opts[@]}" "$@" ) \
|
|
|| print_help "${subcommand}"
|
|
eval args=( "$tmp" )
|
|
unset tmp
|
|
|
|
umask 022
|
|
|
|
subcommand_${Subcommands[$subcommand]} "${args[@]}"
|
|
|
|
# Local Variables:
|
|
# mode: sh
|
|
# sh-basic-offset: 8
|
|
# tab-width: 8
|
|
# End:
|