Krzesimir Nowak 93a26ea067 pkg-auto: Move get_num_proc to util
This will come in handy for spawning jobs for handling package
updates. Since we don't want to spawn as many jobs as there are
packages, then limiting ourselves to the job count matching the
processor or core count sounds like a better idea.
2025-08-21 14:54:04 +02:00

353 lines
8.0 KiB
Bash

#!/bin/bash
if [[ -z ${__UTIL_SH_INCLUDED__:-} ]]; then
__UTIL_SH_INCLUDED__=x
declare -gra EMPTY_ARRAY=()
declare -grA EMPTY_MAP=()
# Works like dirname, but without spawning new processes.
#
# Params:
#
# 1 - path to operate on
# 2 - name of a variable which will contain a dirname of the path
function dirname_out() {
local path dir_var_name
path=${1}; shift
dir_var_name=${1}; shift
local -n dir_ref=${dir_var_name}
if [[ -z ${path} ]]; then
dir_ref='.'
return 0
fi
local cleaned_up dn
# strip trailing slashes
cleaned_up=${path%%*(/)}
# strip duplicated slashes
cleaned_up=${cleaned_up//+(\/)/\/}
# strip last component
dn=${cleaned_up%/*}
if [[ -z ${dn} ]]; then
dir_ref='/'
return 0
fi
if [[ ${cleaned_up} = "${dn}" ]]; then
dir_ref='.'
return 0
fi
dir_ref=${dn}
}
# Works like basename, but without spawning new processes.
#
# Params:
#
# 1 - path to operate on
# 2 - name of a variable which will contain a basename of the path
function basename_out() {
local path base_var_name
path=${1}; shift
base_var_name=${1}; shift
local -n base_ref=${base_var_name}
if [[ -z ${path} ]]; then
base_ref=''
return 0
fi
local cleaned_up dn
# strip trailing slashes
cleaned_up=${path%%*(/)}
if [[ -z ${cleaned_up} ]]; then
base_ref='/'
return 0
fi
# strip duplicated slashes
cleaned_up=${cleaned_up//+(\/)/\/}
# keep last component
dn=${cleaned_up##*/}
base_ref=${dn}
}
if [[ ${BASH_SOURCE[-1]##*/} = 'util.sh' ]]; then
THIS=${BASH}
basename_out "${THIS}" THIS_NAME
THIS_DIR=.
else
THIS=${BASH_SOURCE[-1]}
basename_out "${THIS}" THIS_NAME
dirname_out "${THIS}" THIS_DIR
fi
THIS=$(realpath "${THIS}")
THIS_DIR=$(realpath "${THIS_DIR}")
dirname_out "${BASH_SOURCE[0]}" PKG_AUTO_IMPL_DIR
PKG_AUTO_IMPL_DIR=$(realpath "${PKG_AUTO_IMPL_DIR}")
PKG_AUTO_DIR=$(realpath "${PKG_AUTO_IMPL_DIR}/..")
# Prints an info line.
#
# Params:
#
# @ - strings to print
function info() {
printf '%s: %s\n' "${THIS_NAME}" "${*}"
}
# Prints info lines.
#
# Params:
#
# @ - lines to print
function info_lines() {
printf '%s\n' "${@/#/"${THIS_NAME}: "}"
}
# Prints an info to stderr and fails the execution.
#
# Params:
#
# @ - strings to print
function fail() {
info "${@}" >&2
exit 1
}
# Prints infos to stderr and fails the execution.
#
# Params:
#
# @ - lines to print
function fail_lines() {
info_lines "${@}" >&2
exit 1
}
# Yells a message.
#
# Params:
#
# @ - strings to yell
function yell() {
echo
echo '!!!!!!!!!!!!!!!!!!'
echo " ${*}"
echo '!!!!!!!!!!!!!!!!!!'
echo
}
# Prints help. Help is taken from the lines prefixed with double
# hashes in the top sourcer of this file.
function print_help() {
if [[ ${THIS} != "${BASH}" ]]; then
grep '^##' "${THIS}" | sed -e 's/##[[:space:]]\?//'
fi
}
# Joins passed strings with a given delimiter.
#
# Params:
#
# 1 - name of a variable that will contain the joined result
# 2 - delimiter
# @ - strings to join
function join_by() {
local output_var_name delimiter first
output_var_name=${1}; shift
delimiter=${1}; shift
first=${1-}
if shift; then
printf -v "${output_var_name}" '%s' "${first}" "${@/#/${delimiter}}";
else
local -n output_ref=${output_var_name}
output_ref=''
fi
}
# Checks if directory is empty, returns true if so, otherwise false.
#
# Params:
#
# 1 - path to a directory
function dir_is_empty() {
local dir
dir=${1}; shift
[[ -z $(echo "${dir}"/*) ]]
}
# Just like diff, but ignores the return value.
function xdiff() {
diff "${@}" || :
}
# Just like grep, but ignores the return value.
function xgrep() {
grep "${@}" || :
}
# Strips leading and trailing whitespace from the passed parameter.
#
# Params:
#
# 1 - string to strip
# 2 - name of a variable where the result of stripping will be stored
function strip_out() {
local l
l=${1}; shift
local -n out_ref=${1}; shift
local t
t=${l}
t=${t/#+([[:space:]])}
t=${t/%+([[:space:]])}
out_ref=${t}
}
# Gets supported architectures.
#
# Params:
#
# 1 - name of an array variable, where the architectures will be stored
function get_valid_arches() {
local -n arches_ref=${1}; shift
arches_ref=( 'amd64' 'arm64' )
}
# Generates all pairs from a given sequence of strings. Each pair will
# be stored in the given variable and items in the pair will be
# separated by the given separator. For N strings, (N * N - N) / 2
# pairs will be generatated.
#
# Params:
#
# 1 - name of an array variable where the pairs will be stored
# 2 - separator string
# @ - strings
function all_pairs() {
local -n pairs_ref=${1}; shift
local sep=${1}; shift
# indices in ${@} are 1-based, 0 gives script name or something
local idx=1 next_idx
pairs_ref=()
while [[ ${idx} -lt ${#} ]]; do
next_idx=$((idx + 1))
while [[ ${next_idx} -le ${#} ]]; do
pairs_ref+=( "${!idx}${sep}${!next_idx}" )
next_idx=$((next_idx + 1))
done
idx=$((idx+1))
done
}
# Does the set operation on two passed sets - both set differences and
# an intersection.
#
# Params:
#
# 1 - name of the first set variable
# 2 - name of the second set variable
# 3 - name of the set variable that will contain elements that exist
# in first set, but not the second
# 4 - name of the set variable that will contain elements that exist
# in second set, but not the first
# 5 - name of the set variable that will contain elements that exist
# in both first and second sets
function sets_split() {
local -n first_set_ref=${1}; shift
local -n second_set_ref=${1}; shift
local -n only_in_first_set_ref=${1}; shift
local -n only_in_second_set_ref=${1}; shift
local -n common_set_ref=${1}; shift
only_in_first_set_ref=()
only_in_second_set_ref=()
common_set_ref=()
local item mark
for item in "${!first_set_ref[@]}"; do
mark=${second_set_ref["${item}"]:-}
if [[ -z ${mark} ]]; then
only_in_first_set_ref["${item}"]=x
else
common_set_ref["${item}"]=x
fi
done
for item in "${!second_set_ref[@]}"; do
mark=${first_set_ref["${item}"]:-}
if [[ -z ${mark} ]]; then
only_in_second_set_ref["${item}"]=x
fi
done
}
declare -gi __UTIL_SH_COUNTER=0
# Generates a globally unique name for a variable. Can be given a
# prefix to override the default __PA_VAR one.
#
# Params:
#
# (optional) a prefix
# 1 - name of a variable, where the generated name will be stored
function gen_varname() {
local prefix='__PA_VAR' # pa = pkg-auto
if [[ ${#} -gt 1 ]]; then
# we passed a prefix
prefix=${1}; shift
fi
local -n name_ref=${1}; shift
name_ref="${prefix}_${__UTIL_SH_COUNTER}"
__UTIL_SH_COUNTER=$((__UTIL_SH_COUNTER + 1))
}
# Declares variables with a given initializer.
#
# Params:
#
# @: flags passed to declare, followed by variable names, followed by
# an initializer
function struct_declare() {
local -a args=()
while [[ $# -gt 0 ]]; do
if [[ ${1} != -* ]]; then
break
fi
args+=( "${1}" )
shift
done
if [[ ${#} -lt 2 ]]; then
fail "bad use of struct_declare"
fi
local definition=${*: -1}
set -- "${@:1:$((${#} - 1))}"
set -- "${@/%/=${definition}}"
declare "${args[@]}" "${@}"
}
function get_num_proc() {
local -n num_proc_ref=${1}; shift
local -i num_proc=1 rv=1
# stolen from portage
[[ rv -eq 0 ]] || { rv=0; num_proc=$(getconf _NPROCESSORS_ONLN 2>/dev/null) || rv=1; }
[[ rv -eq 0 ]] || { rv=0; num_proc=$(sysctl -n hw.ncpu 2>/dev/null) || rv=1; }
# stolen from my head
[[ rv -eq 0 ]] || { rv=0; num_proc=$(nproc) || rv=1; }
# stolen from common.sh
[[ rv -eq 0 ]] || { rv=0; num_proc=$(grep -c "^processor" /proc/cpuinfo 2>/dev/null) || rv=1; }
[[ rv -eq 0 ]] || { rv=0; num_proc=1; }
num_proc_ref=${num_proc}
}
fi