Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ci(srcinfo.sh): reduce overhead usage, repair search #6866

Merged
merged 2 commits into from
Jan 12, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
300 changes: 67 additions & 233 deletions scripts/srcinfo.sh
Original file line number Diff line number Diff line change
Expand Up @@ -304,57 +304,34 @@ function srcinfo._contains() {
# @description Create array based on input
#
# @example
# srcinfo._create_array pkgbase var_name var_prefix
# srcinfo._create_array base var_name
#
# @arg $1 string (optional) The pkgbase of the section
# @arg $1 string The pkgbase of the section
# @arg $2 string The variable name
# @arg $3 string (optional) The variable prefix
#
# @stdout Name of array created.
function srcinfo._create_array() {
local pkgbase="${1}" var_name="${2}" var_pref="${3}"
if [[ -n ${pkgbase} ]]; then
pkgbase="${pkgbase//./_}" var_name="${var_name//./_}"
if ! [[ -v "${var_pref}_${pkgbase}_array_${var_name}" ]]; then
declare -ag "${var_pref}_${pkgbase}_array_${var_name}"
fi
echo "${var_pref}_${pkgbase}_array_${var_name}"
else
if ! [[ -v "${var_pref}_array_${var_name}" ]]; then
declare -ag "${var_pref}_array_${var_name}"
fi
echo "${var_pref}_array_${var_name}"
local base="${1}" var_name="${2}"
base="${base//./_}" var_name="${var_name//./_}"
if ! [[ -v "srcinfo_${base}_array_${var_name}" ]]; then
declare -ag "srcinfo_${base}_array_${var_name}"
fi
}

# @description Promote array to variable
#
# @example
# foo=('bar')
# srcinfo._promote_to_variable foo
#
# @arg $1 string Name of array to promote
function srcinfo._promote_to_variable() {
local var_name="${1}" key value
key="${var_name}"
value="${!var_name[0]}"
declare -g "${key}=${value}"
echo "srcinfo_${base}_array_${var_name}"
}

function srcinfo.parse() {
# We need this for trimming whitespace without external tools.
# shellcheck disable=SC2064
trap "$(shopt -p extglob)" RETURN
shopt -s extglob
local srcinfo_file var_prefix locbase temp_array ref total_list loop part i part_two split_up suffix
srcinfo_file="${1:?No .SRCINFO passed to srcinfo.parse}"
var_prefix="${2:?Variable prefix not passed to srcinfo.parse}"
srcinfo.cleanup "${var_prefix}"
[[ ! -s ${srcinfo_file} ]] && return 5
while IFS= read -r line; do
srcinfo.cleanup
local srcfile locbase temp_array ref total_list loop part i suffix
srcfile="${1:?No .SRCINFO passed to srcinfo.parse}"
[[ ! -s ${srcfile} ]] && return 5
mapfile -t srcinfo_data < "${srcfile}"
for line in "${srcinfo_data[@]}"; do
# Skip blank lines
[[ -z ${line} ]] && continue
[[ ${line} =~ ^\s*#.* ]] && continue
[[ -z ${line} || ${line} =~ ^\s*#.* ]] && continue
# Trim leading whitespace.
line="${line##+([[:space:]])}"
declare -A temp_line
Expand All @@ -372,10 +349,10 @@ function srcinfo.parse() {
# Do we have pkgbase first?
if [[ ${temp_line[key]} == "pkgbase" ]]; then
locbase="pkgbase_${temp_line[value]//-/_}"
export globase="${temp_line[value]//./_}"
globase="${temp_line[value]//./_}"
else
locbase="${temp_line[value]//-/_}"
export globase="temporary_pacstall_pkgbase"
globase="temporary_pacstall_pkgbase"
fi
elif [[ ${temp_line[key]} == *"pkgname" ]]; then
# Bash can't have dashes in variable names
Expand All @@ -385,162 +362,38 @@ function srcinfo.parse() {
# So the strategy is to create arrays of every key and at the end,
# we can promote array.len() == 1 to variables instead. After that we
# can work back upwards.
temp_array="$(srcinfo._create_array "${locbase}" "${temp_line[key]}" "${var_prefix}")"
temp_array="$(srcinfo._create_array "${locbase}" "${temp_line[key]}" "srcinfo")"
declare -n ref="${temp_array}"
ref+=("${temp_line[value]}")
if [[ ${locbase} == "pkgbase_"* ]] || ! srcinfo._contains total_list "${temp_array}"; then
if ! srcinfo._contains total_list "${temp_array}"; then
total_list+=("${temp_array}")
fi
done < "${srcinfo_file}"
declare -Ag "${var_prefix}_access"
done
unset srcinfo_data
declare -Ag "srcinfo_access"
for loop in "${total_list[@]}"; do
declare -n part="${loop}"
# Are we at a new pkgname (pkgbase)?
if [[ ${loop} == *@(pkgname|pkgbase) ]]; then
declare -n var_name="${var_prefix}_access"
[[ ${loop} == "${var_prefix}_pkgbase"* ]] && global="pkgbase_"
declare -n var_name="srcinfo_access"
[[ ${loop} == "srcinfo_pkgbase"* ]] && global="pkgbase_"
for i in "${!part[@]}"; do
suffix="${global}${part[${i}]//-/_}"
suffix="${suffix//./_}"
# Create our inner part
declare -ga "${var_prefix}_${suffix}"
declare -ga "srcinfo_${suffix}"
# Declare that relationship
var_name["${var_prefix}_${suffix}"]="${var_prefix}_${suffix}"
var_name["srcinfo_${suffix}"]="srcinfo_${suffix}"
done
unset global
fi
done
for part_two in "${total_list[@]}"; do
# Now we need to go and check every loop over, and parse it out so we get something like ("prefix", "key"), so we can then work with that.
# But first actually we should promote single element arrays to variables
declare -n referoo="${part_two}"
if (("${#referoo[@]}" == 1)); then
srcinfo._promote_to_variable "${part_two}"
fi
mapfile -t split_up <<< "${part_two/_array_/$'\n'}"
declare -n addarr="${split_up[0]}"
unset "${split_up[1]}"
# So now we need to check if the thing we're trying to insert is a variable,
# or an array.
if srcinfo.is_array "${part_two}"; then
declare -ga "${part_two}"
# shellcheck disable=SC2004
addarr[${split_up[1]}]="${part_two}"
else
# shellcheck disable=SC2034,SC2004
addarr[${split_up[1]}]="${!part_two}"
fi
done
}

function srcinfo.cleanup() {
local var_prefix="${1:?No var_prefix passed to srcinfo.cleanup}" i z
local main_loop_template="${var_prefix}_access" compg
declare -n main_loop="${main_loop_template}"
for i in "${main_loop[@]}"; do
declare -n cleaner="${i}"
for z in "${cleaner[@]}"; do
unset "${var_prefix}_array_${z}"
done
unset cleaner
done
unset "${var_prefix}_access" globase global
# So now lets clean the stragglers that we can't reasonably infer
mapfile -t compg < <(compgen -v)
for i in "${compg[@]}"; do
if [[ ${i} == "${var_prefix}_"* ]]; then
unset -v "${i}"
fi
done
}

# @description Reformat numbered associative array to indexed
#
# @example
# srcinfo_depends_vala_panel_appmenu_xfce_git=(["vala-panel-appmenu-valapanel-git-0"]="gtk3")
# srcinfo.reformat_assoc_arr "srcinfo_depends_vala_panel_appmenu_xfce_git" "eviler"
#
# converts to `srcinfo_depends_vala_panel_appmenu_valapanel_git=([0]="gtk3")`
#
# @arg $1 string Associative array to reformat
# @arg $2 string Ref string of indexed array to append conversion to (can be anything)
function srcinfo.reformat_assoc_arr() {
local pfx base ida new pfs in_name="${1}"
local -n in_arr="${in_name}" app="${2}"
IFS='_' read -r -a pfs <<< "${in_name}"
for pfx in "${!in_arr[@]}"; do
base="${pfx%-*}" ida="${pfx##*-}" new="${base//-/_}"
new="${new//./_}"
app+=("$(printf "%s[%s]=\"%s\"\n" "${pfs[0]}_${pfs[1]}_${new}" "${ida}" "${in_arr[${pfx}]}")")
done
}

# @description Parse a specific variable from .SRCINFO
#
# @example
#
# srcinfo.print_var .SRCINFO source
# @arg $1 string .SRCINFO file path
# @arg $2 string Variable or Array to print
function srcinfo.print_var() {
local srcinfo_file="${1}" found="${2}" var_prefix="srcinfo" pkgbase output var name idx evil eviler e printed
local -n bases="${var_prefix}_access"
srcinfo.parse "${srcinfo_file}" "${var_prefix}"
if [[ ${found} == "pkgbase" ]]; then
if [[ -n ${globase} && ${globase} != "temporary_pacstall_pkgbase" ]]; then
pkgbase="${globase}"
declare -p pkgbase
return 0
else
return 3
fi
fi
for var in "${bases[@]}"; do
var="${var//./_}"
declare -n output="${var}_array_${found}"
declare -n name="${var}_array_pkgname"
if [[ -n ${output[*]} ]]; then
for idx in "${!output[@]}"; do
if ((${#bases[@]} > 1)); then
# shellcheck disable=SC2076
if [[ ${var} =~ "pkgbase_${globase//-/_}" ]]; then
evil+=("$(printf "${var_prefix}_${found}_${globase//-/_}[\"${globase}-pkgbase-%d\"]=\"%s\"\n" "${idx}" "${output[${idx}]}")")
else
evil+=("$(printf "${var_prefix}_${found}_${globase//-/_}[\"${name}-%d\"]=\"%s\"\n" "${idx}" "${output[${idx}]}")")
fi
else
evil+=("$(printf "${var_prefix}_${found}_${name//-/_}[\"${name}-%d\"]=\"%s\"\n" "${idx}" "${output[${idx}]}")")
fi
done
fi
done
if [[ -n ${globase} && ${globase} != "temporary_pacstall_pkgbase" ]]; then
unset "${var_prefix}_${found}_${globase//-/_}"
declare -Ag "${var_prefix}_${found}_${globase//-/_}"
else
unset "${var_prefix}_${found}_${name//-/_}"
declare -Ag "${var_prefix}_${found}_${name//-/_}"
fi
# shellcheck disable=SC2294
eval "${evil[@]}"
if [[ -n ${globase} && ${globase} != "temporary_pacstall_pkgbase" ]]; then
srcinfo.reformat_assoc_arr "${var_prefix}_${found}_${globase//-/_}" "eviler"
unset "${var_prefix}_${found}_${globase//-/_}"
# shellcheck disable=SC2294
eval "${eviler[@]}"
else
srcinfo.reformat_assoc_arr "${var_prefix}_${found}_${name//-/_}" "eviler"
unset "${var_prefix}_${found}_${name//-/_}"
# shellcheck disable=SC2294
eval "${eviler[@]}"
fi
for e in "${eviler[@]}"; do
if ! srcinfo._contains printed "${e%\[*}"; then
printed+=("${e%\[*}")
declare -p "${e%\[*}"
fi
unset "${e%\[*}"
done
local compg
mapfile -t compg < <(compgen -v "srcinfo_")
unset "${compg[@]}" srcinfo_access globase global 2> /dev/null
}

# @description Output a specific variable from .SRCINFO
Expand All @@ -553,46 +406,22 @@ function srcinfo.print_var() {
# @arg $2 string Variable or Array to search
# @arg $3 string Package name or base to get output for
function srcinfo.match_pkg() {
local declares d bases b guy match out srcfile="${1}" search="${2}" pkg="${3}"
local srcinfo_file="${1}" search="${2}" pkg="${3}" pkgbase output var
local -n bases="srcinfo_access"
pkg="${pkg//./_}"
if [[ ${pkg} == "pkgbase:"* || ${search} == "pkgbase" ]]; then
pkg="${pkg/pkgbase:/}"
match="srcinfo_${search%%_*}_${pkg//-/_}_pkgbase"
else
match="srcinfo_${search%%_*}_${pkg//-/_}"
fi
mapfile -t declares < <(srcinfo.print_var "${srcfile}" "${search}" | awk '{sub(/^declare -a |^declare -- |^declare -x /, ""); print}')
[[ ${search} == "pkgbase" && -z ${declares[*]} ]] \
&& mapfile -t declares < <(srcinfo.print_var "${srcfile}" "pkgname" | awk '{sub(/^declare -a |^declare -- |^declare -x /, ""); print}')
for d in "${declares[@]}"; do
if [[ ${d%=\(*} =~ = ]]; then
declare -- "${d}"
bases+=("${d%=*}")
else
declare -a "${d}"
bases+=("${d%=\(*}")
fi
done
for b in "${bases[@]}"; do
guy="${b}[@]"
if [[ -z ${pkg} ]]; then
if [[ ${search} == "pkgname" || ${search} == "pkgbase" ]]; then
if [[ -n ${pkgbase} ]]; then
out="${pkgbase/\"/}"
out="${out/\"/}"
printf '%s\n' "pkgbase:${out}"
continue
fi
printf '%s\n' "${!guy}"
continue
else
printf '%s\n' "${guy}"
continue
pkg="${pkg//:/_}"
pkg="${pkg//-/_}"
srcinfo.parse "${srcinfo_file}"
for var in "${bases[@]}"; do
var="${var//./_}"
declare -n output="${var}_array_${search}"
if [[ -n ${output[*]} ]]; then
if [[ ${search} == "pkgbase" ]]; then
echo "pkgbase:${output[0]}"
elif [[ ${search} == "pkgname" || ${var}_array_${search} == "srcinfo_${pkg}_array_${search}" ]]; then
printf '%s\n' "${output[@]}"
fi
fi
if [[ ${b} == "${match}" ]]; then
printf '%s\n' "${!guy}"
fi
done
}

Expand Down Expand Up @@ -663,45 +492,50 @@ function srcinfo.list_search() {
function print_pkgbase_and_pkgname() {
if (pkgbase != "") {
print pkgbase, pkgbase_desc
if (pkgname != "") {
desc = (pkgname_desc != "" ? pkgname_desc : pkgbase_desc)
print pkgbase ":" pkgname, desc
for (i in pkgnames) {
desc = (pkgname_descs[i] != "" ? pkgname_descs[i] : pkgbase_desc)
print pkgbase ":" pkgnames[i], desc
}
}
}
/^---$/ {
if (pkgbase != "" && (pkgbase ~ kw || tolower(pkgbase_desc) ~ kw)) {
print_pkgbase_and_pkgname()
found = 1
} else if (pkgname != "" && (pkgname ~ kw || tolower(pkgname_desc) ~ kw)) {
print_pkgbase_and_pkgname()
found = 1
if (pkgbase != "") {
if (pkgbase ~ kw || tolower(pkgbase_desc) ~ kw || kw == "") {
print_pkgbase_and_pkgname()
found = 1
} else {
for (i in pkgnames) {
desc = (pkgname_descs[i] != "" ? pkgname_descs[i] : pkgbase_desc)
if (pkgnames[i] ~ kw || tolower(desc) ~ kw) {
print pkgbase ":" pkgnames[i], desc
found = 1
}
}
}
}
pkgname = ""; pkgbase = ""; pkgbase_desc = ""; pkgname_desc = ""; next
pkgbase = ""; pkgbase_desc = ""; delete pkgnames; delete pkgname_descs
next
}
/^[[:space:]]*pkgbase[[:space:]]*=/ {
pkgbase = $2
pkgbase_desc = ""
}
/^[[:space:]]*pkgname[[:space:]]*=/ {
if (pkgname != "") {
desc = (pkgname_desc != "" ? pkgname_desc : pkgbase_desc)
if (pkgname ~ kw || tolower(desc) ~ kw) {
print pkgbase ":" pkgname, desc
found = 1
}
}
pkgname = $2
pkgname_desc = ""
# Add pkgname to array
pkgnames[length(pkgnames) + 1] = $2
pkgname_descs[length(pkgnames)] = ""
}
/^[[:space:]]*pkgdesc[[:space:]]*=/ {
if (pkgname == "") {
if (length(pkgnames) == 0) {
pkgbase_desc = $2
} else {
pkgname_desc = $2
pkgname_descs[length(pkgnames)] = $2
}
}
END {
if (pkgbase != "") {
print_pkgbase_and_pkgname()
}
if (!found) {
print "No matching packages found"
}
Expand Down
Loading