mirror of
https://github.com/Pmodules/Pmodules.git
synced 2026-06-27 10:03:08 +02:00
Merge branch '105-module-search-add-option-to-output-all-dependencies-in' into 'master'
Resolve "module search: add option to output all dependencies in" Closes #105 See merge request Pmodules/src!73
This commit is contained in:
+237
-96
@@ -18,6 +18,7 @@ declare -r base64="${sbindir}/base64"
|
||||
declare -r mktemp="${sbindir}/mktemp"
|
||||
declare -r sort="${sbindir}/sort"
|
||||
declare -r getopt="${sbindir}/getopt"
|
||||
declare -r find="${sbindir}/find"
|
||||
|
||||
source "${libdir}/libstd.bash"
|
||||
source "${libdir}/libpmodules.bash"
|
||||
@@ -35,6 +36,10 @@ fi
|
||||
|
||||
declare verbosity_lvl=${PMODULES_VERBOSITY:-'verbose'}
|
||||
|
||||
# we use newline as internal field separator
|
||||
IFS=$' \t\n'
|
||||
declare -r __IFS=${IFS} # used to restore IFS
|
||||
|
||||
shopt -s nullglob
|
||||
|
||||
declare -A GroupDepths='()'
|
||||
@@ -263,10 +268,9 @@ subcommand_load() {
|
||||
local prefix=''
|
||||
local m=''
|
||||
|
||||
local saved_IFS="${IFS}";
|
||||
IFS=':'
|
||||
local -a modulepath=(${MODULEPATH})
|
||||
IFS=${saved_IFS}
|
||||
IFS=${__IFS}
|
||||
|
||||
#
|
||||
# Test whether a given module is available.
|
||||
@@ -407,10 +411,9 @@ subcommand_load() {
|
||||
# - release:group:name or
|
||||
# - name:release
|
||||
|
||||
local save_ifs=${IFS}
|
||||
IFS=':'
|
||||
local -a toks=($m)
|
||||
IFS=${save_ifs}
|
||||
IFS=${__IFS}
|
||||
local group=''
|
||||
local release=''
|
||||
if is_group "${toks[0]}"; then
|
||||
@@ -715,22 +718,28 @@ subcommand_show() {
|
||||
# modulename1 release1 modulename2 release2 ...
|
||||
#
|
||||
get_available_modules() {
|
||||
local -r dir="$1"
|
||||
local -r module="$2"
|
||||
local -r use_releases="${3:-${UsedReleases}}"
|
||||
local -r module="$1"
|
||||
local -r use_releases="${2:-${UsedReleases}}"
|
||||
shift 2
|
||||
local -a dirs=( "$@" )
|
||||
|
||||
local -a mods=()
|
||||
local release
|
||||
test -d "${dir}" || return 0
|
||||
{
|
||||
cd "${dir}"
|
||||
while read mod; do
|
||||
get_release release "${dir}/${mod}"
|
||||
|
||||
if [[ :${use_releases}: =~ :${release}: ]]; then
|
||||
mods+=( "${mod}" ${release} )
|
||||
fi
|
||||
done < <(find * \( -type f -o -type l \) -not -name ".*" -ipath "${module}*")
|
||||
}
|
||||
local dir=''
|
||||
|
||||
for dir in "${dirs[@]}"; do
|
||||
test -d "${dir}" || return 0
|
||||
{
|
||||
cd "${dir}"
|
||||
while read mod; do
|
||||
get_release release "${dir}/${mod}"
|
||||
|
||||
if [[ :${use_releases}: =~ :${release}: ]]; then
|
||||
mods+=( "${mod}" ${release} "${dir}/${mod}")
|
||||
fi
|
||||
done < <(${find} * \( -type f -o -type l \) -not -name ".*" -ipath "${module}*")
|
||||
}
|
||||
done
|
||||
echo "${mods[@]}"
|
||||
}
|
||||
|
||||
@@ -790,7 +799,7 @@ subcommand_avail() {
|
||||
|
||||
terse_output() {
|
||||
output_header
|
||||
for (( i=0; i<${#mods[@]}; i+=2 )); do
|
||||
for (( i=0; i<${#mods[@]}; i+=3 )); do
|
||||
local mod=${mods[i]}
|
||||
local release=${mods[i+1]}
|
||||
case $release in
|
||||
@@ -807,7 +816,7 @@ subcommand_avail() {
|
||||
}
|
||||
|
||||
machine_output() {
|
||||
for (( i=0; i<${#mods[@]}; i+=2 )); do
|
||||
for (( i=0; i<${#mods[@]}; i+=3 )); do
|
||||
printf "%-20s\t%s\n" "${mods[i]}" "${mods[i+1]}" 1>&2
|
||||
done
|
||||
}
|
||||
@@ -816,7 +825,7 @@ subcommand_avail() {
|
||||
# :FIXME: for the time being, this is the same as terse_output!
|
||||
long_output() {
|
||||
output_header
|
||||
for (( i=0; i<${#mods[@]}; i+=2 )); do
|
||||
for (( i=0; i<${#mods[@]}; i+=3 )); do
|
||||
local mod=${mods[i]}
|
||||
local release=${mods[i+1]}
|
||||
case $release in
|
||||
@@ -837,7 +846,7 @@ subcommand_avail() {
|
||||
|
||||
local -i column=$cols
|
||||
local -i colsize=16
|
||||
for ((i=0; i<${#mods[@]}; i+=2)); do
|
||||
for ((i=0; i<${#mods[@]}; i+=3 )); do
|
||||
if [[ ${verbosity_lvl} == 'verbose' ]]; then
|
||||
local release=${mods[i+1]}
|
||||
case ${mods[i+1]} in
|
||||
@@ -907,16 +916,16 @@ subcommand_avail() {
|
||||
if (( ${#pattern[@]} == 0 )); then
|
||||
pattern+=( '' )
|
||||
fi
|
||||
local saved_IFS=${IFS};
|
||||
IFS=':'
|
||||
local -a modulepath=(${MODULEPATH})
|
||||
IFS=${saved_IFS}
|
||||
IFS=${__IFS}
|
||||
local string
|
||||
for string in "${pattern[@]}"; do
|
||||
for dir in "${modulepath[@]}"; do
|
||||
mods=( $( get_available_modules \
|
||||
"${dir}" "${string}" \
|
||||
"${opt_use_releases}" ) )
|
||||
"${string}" \
|
||||
"${opt_use_releases}" \
|
||||
"${dir}" ) )
|
||||
[[ ${#mods[@]} == 0 ]] && continue
|
||||
${output_function}
|
||||
done
|
||||
@@ -935,7 +944,7 @@ compute_group_depth () {
|
||||
local group=${dir%/*}
|
||||
local group=${group##*/}
|
||||
[[ -n "${GroupDepths[${group}]}" ]] && return 0
|
||||
local -i depth=$(find "${dir}" -depth \( -type f -o -type l \) \
|
||||
local -i depth=$(${find} "${dir}" -depth \( -type f -o -type l \) \
|
||||
-printf "%d" -quit 2>/dev/null)
|
||||
(( depth-=2 ))
|
||||
# if a group doesn't contain a modulefile, depth is negativ
|
||||
@@ -991,10 +1000,9 @@ SWITCHES:
|
||||
|
||||
subcommand_use() {
|
||||
local -r subcommand='use'
|
||||
local saved_IFS=${IFS};
|
||||
IFS=':'
|
||||
local -a modulepath=(${MODULEPATH})
|
||||
IFS=${saved_IFS}
|
||||
IFS=${__IFS}
|
||||
local add2path_func='std::append_path'
|
||||
|
||||
group_is_used() {
|
||||
@@ -1483,7 +1491,9 @@ subcommand_clear() {
|
||||
#
|
||||
Subcommands[search]='search'
|
||||
Options[search]='-o aH -l help -l no-header -l print-modulefiles '
|
||||
Options[search]+='-l release: -l with: -l all-releases -l src: -l print-csv'
|
||||
Options[search]+='-l release: -l with: -l all-releases -l src: -l print-csv '
|
||||
Options[search]+='-l verbose '
|
||||
Options[search]+='-l all-deps -l wrap'
|
||||
Help[search]='
|
||||
USAGE:
|
||||
module search [switches] string...
|
||||
@@ -1509,26 +1519,28 @@ SWITCHES:
|
||||
module search --with=gcc/4.8.3
|
||||
|
||||
lists all modules in the hierarchy compiled with gcc 4.8.3.
|
||||
|
||||
--verbose
|
||||
vebose output
|
||||
|
||||
--wrap
|
||||
wrap output
|
||||
'
|
||||
|
||||
subcommand_search() {
|
||||
local -r subcommand='search'
|
||||
local modules=()
|
||||
local with_modules='//'
|
||||
local src_prefix=''
|
||||
local -ir cols=$(tput cols) # get number of columns of terminal
|
||||
local -i max_len_modulename=0
|
||||
local src_prefix=()
|
||||
local opt_print_header='yes'
|
||||
local opt_print_modulefiles='no'
|
||||
local opt_print_csv='no'
|
||||
local opt_print_verbose='no'
|
||||
local opt_use_releases=':'
|
||||
local -r fmt="%-20s %-10s %-12s %-s\n"
|
||||
|
||||
# no args
|
||||
print_header() {
|
||||
printf '\n' 1>&1
|
||||
printf "${fmt}" "Module" "Release" "Group" "Requires" 1>&2
|
||||
printf -- '-%.0s' {1..60} 1>&2
|
||||
printf '\n' 1>&2
|
||||
}
|
||||
local opt_all_deps='no'
|
||||
local opt_wrap='no'
|
||||
|
||||
#.....................................................................
|
||||
#
|
||||
@@ -1542,31 +1554,132 @@ subcommand_search() {
|
||||
# with_modules
|
||||
#
|
||||
print_result() {
|
||||
local -r tmpfile=$1
|
||||
[[ "${opt_print_header}" == "yes" ]] && print_header
|
||||
if [[ "${opt_print_modulefiles}" == "yes" ]]; then
|
||||
while read -a line; do
|
||||
# group first
|
||||
local out="${line[2]}/"
|
||||
# add directory of modulefiles
|
||||
out+="${PMODULES_MODULEFILES_DIR}/"
|
||||
for d in "${line[@]:3}"; do
|
||||
out+="$d/"
|
||||
local func_print_header=''
|
||||
local func_print_line=''
|
||||
local fmt=''
|
||||
|
||||
print_default() {
|
||||
fmt="%-${max_len_modulename}s %-10s %-12s %-s"
|
||||
if [[ ${opt_print_header} == 'yes' ]]; then
|
||||
func_print_header='print_header_default'
|
||||
else
|
||||
func_print_header='print_header_none'
|
||||
fi
|
||||
func_print_line='print_line_default'
|
||||
}
|
||||
|
||||
print_header_default() {
|
||||
std::info ''
|
||||
std::info "${fmt}" "Module" "Release" "Group" "Requires"
|
||||
std::info '-%.0s' $(seq 1 ${cols})
|
||||
}
|
||||
|
||||
print_line_default() {
|
||||
write_line() {
|
||||
local str="$1"
|
||||
if (( ${#str} >= cols )); then
|
||||
str="${str:0:$((cols-1))}>"
|
||||
fi
|
||||
std::info "${str}"
|
||||
}
|
||||
if [[ "${opt_wrap}" == 'no' ]]; then
|
||||
local deps="${@:5}"
|
||||
local str=$(printf "${fmt}" "$1" "$2" "$3" "${deps[@]}")
|
||||
write_line "${str}"
|
||||
else
|
||||
local deps=( "${@:5}" )
|
||||
local str=$(printf "${fmt}" "$1" "$2" "$3" "${deps[0]}")
|
||||
for (( i = 1; i < ${#deps[@]}; i++ )); do
|
||||
if (( ${#str} + ${#deps[i]} + 1 <= cols )); then
|
||||
str+=" ${deps[i]}"
|
||||
else
|
||||
write_line "${str}"
|
||||
str=$(printf "${fmt}" "" "" "" "> ${deps[i]}")
|
||||
fi
|
||||
done
|
||||
out+="${line[0]}"
|
||||
std::info "${out}"
|
||||
done < <("${sort}" -k 1,1 -k 4,4 -k 5,5 "${tmpfile}" | \
|
||||
awk "${with_modules}")
|
||||
elif [[ "${opt_print_csv}" == "yes" ]]; then
|
||||
while read -a toks; do
|
||||
:
|
||||
done < <("${sort}" -k 1,1 -k 4,4 -k 5,5 "${tmpfile}" | \
|
||||
awk "${with_modules}")
|
||||
else
|
||||
"${sort}" -k 1,1 -k 4,4 -k 5,5 "${tmpfile}" | \
|
||||
awk "${with_modules}" 1>&2
|
||||
fi
|
||||
write_line "${str}"
|
||||
fi
|
||||
}
|
||||
|
||||
print_verbose() {
|
||||
fmt="%-${max_len_modulename}s %-10s %-12s %-s"
|
||||
func_print_header='print_header_verbose'
|
||||
func_print_line='print_line_verbose'
|
||||
}
|
||||
|
||||
print_header_verbose() {
|
||||
std::info ''
|
||||
std::info "${fmt}" "Module" "Release" "Group" "Dependencies/Modulefile"
|
||||
std::info '-%.0s' $(seq 1 ${cols})
|
||||
}
|
||||
|
||||
print_line_verbose() {
|
||||
local deps="${@:5}"
|
||||
std::info "${fmt}" "$1" "$2" "$3" "dependencies: ${deps}"
|
||||
std::info "${fmt}" "" "" "" "modulefile: $4"
|
||||
}
|
||||
|
||||
# print full modulefile names only
|
||||
print_modulefiles() {
|
||||
fmt=''
|
||||
func_print_header='print_header_none'
|
||||
func_print_line='print_header_none'
|
||||
}
|
||||
|
||||
print_header_none() {
|
||||
:
|
||||
}
|
||||
|
||||
print_line_modulefile() {
|
||||
local line=( "$@" )
|
||||
# group first
|
||||
local out="${line[2]}/"
|
||||
# add directory of modulefiles
|
||||
out+="${PMODULES_MODULEFILES_DIR}/"
|
||||
for d in "${line[@]:3}"; do
|
||||
out+="$d/"
|
||||
done
|
||||
out+="${line[0]}"
|
||||
std::info "${out}"
|
||||
}
|
||||
|
||||
print_line_csv() {
|
||||
:
|
||||
}
|
||||
|
||||
print_csv() {
|
||||
fmt=''
|
||||
func_print_header='print_header_none'
|
||||
func_print_line='print_line_csv'
|
||||
}
|
||||
|
||||
local -r tmpfile=$1
|
||||
|
||||
if [[ "${opt_print_modulefiles}" == 'yes' ]]; then
|
||||
print_modulefiles
|
||||
elif [[ "${opt_print_csv}" == 'yes' ]]; then
|
||||
print_csv
|
||||
elif [[ "${opt_print_verbose}" == 'yes' ]]; then
|
||||
print_verbose
|
||||
else
|
||||
print_default
|
||||
fi
|
||||
|
||||
${func_print_header}
|
||||
while read -a toks; do
|
||||
${func_print_line} "${toks[@]}"
|
||||
done < <("${sort}" -k 1,1 -k 4,4 -k 5,5 "${tmpfile}" | \
|
||||
awk "${with_modules}")
|
||||
}
|
||||
|
||||
get_module_prefix() {
|
||||
local "$1"
|
||||
local modulefile="$2"
|
||||
local -r _prefix=$("${modulecmd}" bash show "${modulefile}" 2>&1 | \
|
||||
awk '/_PREFIX |_HOME / {print $3; exit}')
|
||||
std::upvar $1 "${_prefix}"
|
||||
}
|
||||
|
||||
#.....................................................................
|
||||
#
|
||||
# search modules
|
||||
@@ -1580,47 +1693,65 @@ subcommand_search() {
|
||||
local -r module=$1
|
||||
# write results to a temporary file for later processing
|
||||
local -r tmpfile=$( "${mktemp}" /tmp/Pmodules.XXXXXX ) \
|
||||
|| std::die 1 "Oops: unable to create tmp file!\n"
|
||||
|| std::die 1 "Oops: unable to create tmp file!"
|
||||
local group
|
||||
# loop over all groups
|
||||
for group in "${!GroupDepths[@]}"; do
|
||||
# loop over all directories which can be added to
|
||||
# MODULEPATH inside current group
|
||||
local depth=${GroupDepths[${group}]}
|
||||
local mpaths=( $(find \
|
||||
"${src_prefix}/${group}/modulefiles" \
|
||||
-type d \
|
||||
-mindepth ${depth} -maxdepth ${depth} \
|
||||
2>/dev/null))
|
||||
local mpath
|
||||
for mpath in "${mpaths[@]}"; do
|
||||
# get dependencies encoded in directory name
|
||||
local p="${mpath/${src_prefix}}"
|
||||
p=( ${p//\// } )
|
||||
local deps=()
|
||||
local -i i
|
||||
for ((i=2; i < ${#p[@]}; i+=2)); do
|
||||
deps+=( ${p[i]}/${p[i+1]} )
|
||||
done
|
||||
local requires=${deps[@]}
|
||||
local s=''
|
||||
if (( depth > 0 )); then
|
||||
s=$(printf '/*%.0s' $(seq 1 ${depth}))
|
||||
fi
|
||||
local modulepath=( ${src_prefix[@]/%//${group}/modulefiles$s} )
|
||||
|
||||
# get and print all available modules in $mpath
|
||||
# with respect to the requested releases
|
||||
# tmpfile: module/version release group group-
|
||||
# dependencies...
|
||||
local mods=( $( get_available_modules \
|
||||
"${module}" \
|
||||
"${opt_use_releases}" \
|
||||
"${modulepath[@]}" \
|
||||
) )
|
||||
|
||||
# get and print all available modules in $mpath
|
||||
# with respect to the requested releases
|
||||
# tmpfile: module/version release group group-
|
||||
# dependencies...
|
||||
local mods=( $( get_available_modules \
|
||||
"${mpath}" \
|
||||
"${module}" \
|
||||
"${opt_use_releases}" ) )
|
||||
[[ ${#mods[@]} == 0 ]] && continue
|
||||
for (( i=0; i<${#mods[@]}; i+=2 )); do
|
||||
printf "${fmt}" ${mods[i]} "${mods[i+1]}" \
|
||||
${group} "${requires}" >> "${tmpfile}"
|
||||
done
|
||||
for (( i=0; i<${#mods[@]}; i+=3 )); do
|
||||
local name=${mods[i]}
|
||||
local release=${mods[i+1]}
|
||||
local modulefile=${mods[i+2]}
|
||||
|
||||
if (( ${#name} > max_len_modulename)); then
|
||||
max_len_modulename=${#name}
|
||||
fi
|
||||
|
||||
if [[ "${opt_print_verbose}" == 'yes' ]] || [[ "${opt_all_deps}" == 'yes' ]]; then
|
||||
local prefix=''
|
||||
get_module_prefix prefix "${modulefile}"
|
||||
local dependencies_file="${prefix}/.dependencies"
|
||||
if [[ -n ${prefix} ]] && [[ -r "${dependencies_file}" ]]; then
|
||||
deps=($(< "${dependencies_file}"))
|
||||
else
|
||||
deps=()
|
||||
fi
|
||||
else
|
||||
# get dependencies encoded in directory name
|
||||
local deps=()
|
||||
local -i j
|
||||
IFS='/'
|
||||
local toks=( ${modulefile} )
|
||||
for ((j = -depth-2; j < -2; j += 2)); do
|
||||
deps+=( "${toks[*]: $j:2}" );
|
||||
done
|
||||
IFS=${__IFS}
|
||||
fi
|
||||
|
||||
echo ${name} ${release} ${group} ${modulefile} \
|
||||
${deps[@]} >> "${tmpfile}"
|
||||
done
|
||||
done
|
||||
print_result "${tmpfile}"
|
||||
rm -f "${tmpfile}"
|
||||
#rm -f "${tmpfile}"
|
||||
}
|
||||
|
||||
while (( $# > 0 )); do
|
||||
@@ -1628,6 +1759,9 @@ subcommand_search() {
|
||||
-H | --help )
|
||||
print_help "${subcommand}"
|
||||
;;
|
||||
--all-deps )
|
||||
opt_all_deps='yes'
|
||||
;;
|
||||
--no-header )
|
||||
opt_print_header='no'
|
||||
;;
|
||||
@@ -1647,7 +1781,7 @@ subcommand_search() {
|
||||
local arg=${1/--release=}
|
||||
fi
|
||||
is_release "${arg}" || \
|
||||
std::die 1 "%s %s: %s -- %s\n" \
|
||||
std::die 1 "%s %s: %s -- %s" \
|
||||
"${CMD}" 'search' \
|
||||
"illegal release name" \
|
||||
"${arg}"
|
||||
@@ -1661,7 +1795,7 @@ subcommand_search() {
|
||||
local arg=${1/--with=}
|
||||
fi
|
||||
if [[ -z ${arg} ]] || [[ "${arg}" =~ "-*" ]]; then
|
||||
std::die 1 "%s %s: %s -- %s\n" \
|
||||
std::die 1 "%s %s: %s -- %s" \
|
||||
"${CMD}" 'search' \
|
||||
"illegal value for --with option" \
|
||||
"${arg}"
|
||||
@@ -1680,6 +1814,12 @@ subcommand_search() {
|
||||
pmodules::check_directories "${src_prefix}"
|
||||
shift
|
||||
;;
|
||||
-v | --verbose )
|
||||
opt_print_verbose='yes'
|
||||
;;
|
||||
--wrap )
|
||||
opt_wrap='yes'
|
||||
;;
|
||||
-- )
|
||||
;;
|
||||
* )
|
||||
@@ -1700,6 +1840,7 @@ subcommand_search() {
|
||||
modules+=( '' )
|
||||
fi
|
||||
|
||||
# :FIXME: do we need this?
|
||||
if (( ${#GroupDepths[@]} == 0 )) || \
|
||||
[[ ${src_prefix} != ${PMODULES_ROOT} ]]; then
|
||||
scan_groups "${src_prefix}"
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env modbuild
|
||||
|
||||
pbuild::set_download_url "https://ftp.gnu.org/pub/gnu/$P/$P-$V.tar.xz"
|
||||
pbuild::add_configure_args "--bindir=${PREFIX}/sbin"
|
||||
@@ -345,6 +345,10 @@ pmodules::compile() {
|
||||
build bash
|
||||
fi
|
||||
|
||||
if [[ ! -f "${PMODULES_HOME}/sbin/find" ]] || [[ ${opt_force} == 'yes' ]]; then
|
||||
build findutils
|
||||
fi
|
||||
|
||||
if [[ ! -e "${PMODULES_HOME}/sbin/tclsh" ]] || [[ ${opt_force} == 'yes' ]]; then
|
||||
build Tcl
|
||||
fi
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
bash 5.1-rc3
|
||||
coreutils 8.31
|
||||
findutils 4.7.0
|
||||
getopt 1.1.6
|
||||
gettext 0.21
|
||||
modules 3.2.10.1
|
||||
|
||||
Reference in New Issue
Block a user