mirror of
https://github.com/flatcar/scripts.git
synced 2025-08-11 06:56:58 +02:00
This adds some scripts I have been using for over a year to deal with the weekly package updates. It comes with a `README.md` which describes a workflow similar to my own. The `sync_packages.sh` and `update_packages.sh` scripts are currently not used anywhere. The idea behind them was to use them for Github Action, but that will come as a follow-up PR.
275 lines
7.3 KiB
Bash
Executable File
275 lines
7.3 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
##
|
|
## Prints profile information in form of an inheritance tree and/or
|
|
## evaluation order.
|
|
##
|
|
## Parameters:
|
|
## -h: this help
|
|
## -ni: no inheritance tree
|
|
## -ne: no evaluation order
|
|
## -nh: no headers
|
|
##
|
|
## Environment variables:
|
|
## ROOT
|
|
##
|
|
|
|
set -euo pipefail
|
|
|
|
source "$(dirname "${BASH_SOURCE[0]}")/util.sh"
|
|
|
|
: "${ROOT:=/}"
|
|
|
|
print_inheritance_tree=x
|
|
print_evaluation_order=x
|
|
print_headers=x
|
|
|
|
while [[ ${#} -gt 0 ]]; do
|
|
case ${1} in
|
|
-h)
|
|
print_help
|
|
exit 0
|
|
;;
|
|
-ni)
|
|
print_inheritance_tree=
|
|
;;
|
|
-ne)
|
|
print_evaluation_order=
|
|
;;
|
|
-nh)
|
|
print_headers=
|
|
;;
|
|
*)
|
|
fail "unknown flag ${1}"
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
all_repo_names=()
|
|
read -a all_repo_names -r < <(portageq get_repos "${ROOT}")
|
|
|
|
declare -A repo_data repo_data_r
|
|
# name to path
|
|
repo_data=()
|
|
# path to name
|
|
repo_data_r=()
|
|
|
|
for repo_name in "${all_repo_names[@]}"; do
|
|
repo_path=$(portageq get_repo_path "${ROOT}" "${repo_name}")
|
|
repo_path=$(realpath "${repo_path}")
|
|
repo_data["${repo_name}"]="${repo_path}"
|
|
repo_data_r["${repo_path}"]="${repo_name}"
|
|
done
|
|
|
|
unset all_repo_names
|
|
|
|
function get_repo_from_profile_path() {
|
|
local path
|
|
path=${1}; shift
|
|
local -n repo_dir_ref=${1}; shift
|
|
|
|
# shellcheck disable=SC2034 # it's a reference to external variable
|
|
repo_dir_ref="${path%/profiles/*}"
|
|
}
|
|
|
|
function repo_path_to_name() {
|
|
local path
|
|
path=${1}; shift
|
|
local -n name_ref=${1}; shift
|
|
|
|
# shellcheck disable=SC2034 # it's a reference to external variable
|
|
name_ref=${repo_data_r["${path}"]:-'<unknown>'}
|
|
}
|
|
|
|
function repeat_string() {
|
|
local str ntimes out_str_var_name
|
|
str=${1}; shift
|
|
ntimes=${1}; shift
|
|
out_str_var_name=${1}; shift
|
|
local -n out_str_ref="${out_str_var_name}"
|
|
|
|
if [[ ${ntimes} -eq 0 ]]; then
|
|
out_str_ref=""
|
|
return 0
|
|
elif [[ ${ntimes} -eq 1 ]]; then
|
|
out_str_ref="${str}"
|
|
return 0
|
|
fi
|
|
local add_one
|
|
add_one=$((ntimes % 2))
|
|
repeat_string "${str}${str}" $((ntimes / 2)) "${out_str_var_name}"
|
|
if [[ add_one -gt 0 ]]; then
|
|
out_str_ref+="${str}"
|
|
fi
|
|
}
|
|
|
|
function process_profile() {
|
|
local repo_name profile_path
|
|
repo_name=${1}; shift
|
|
profile_path=${1}; shift
|
|
local -n children_ref=${1}; shift
|
|
|
|
local parent_file line pp_new_repo_name new_profile_path pp_new_repo_path
|
|
local -a children
|
|
|
|
parent_file="${profile_path}/parent"
|
|
children=()
|
|
if [[ -e ${parent_file} ]]; then
|
|
while read -r line; do
|
|
if [[ ${line} = *:* ]]; then
|
|
pp_new_repo_name=${line%%:*}
|
|
if [[ -z ${pp_new_repo_name} ]]; then
|
|
pp_new_repo_name=${repo_name}
|
|
fi
|
|
pp_new_repo_path=${repo_data["${pp_new_repo_name}"]}
|
|
new_profile_path="${pp_new_repo_path}/profiles/${line#*:}"
|
|
children+=( "${pp_new_repo_name}" "${new_profile_path}" )
|
|
elif [[ ${line} = /* ]]; then
|
|
pp_new_repo_path=
|
|
get_repo_from_profile_path "${line}" pp_new_repo_path
|
|
pp_new_repo_name=
|
|
repo_path_to_name "${pp_new_repo_path}" pp_new_repo_name
|
|
children+=( "${pp_new_repo_name}" "${line}" )
|
|
else
|
|
pp_new_repo_path=$(realpath "${profile_path}/${line}")
|
|
children+=( "${repo_name}" "${pp_new_repo_path}" )
|
|
fi
|
|
done <"${parent_file}"
|
|
fi
|
|
|
|
# shellcheck disable=SC2034 # it's a reference to external variable
|
|
children_ref=( "${children[@]}" )
|
|
}
|
|
|
|
function get_profile_name() {
|
|
local repo_name profile_path
|
|
repo_name="${1}"; shift
|
|
profile_path="${1}"; shift
|
|
local -n profile_name_ref=${1}; shift
|
|
|
|
local repo_path profile_name
|
|
repo_path=${repo_data["${repo_name}"]}
|
|
profile_name=${profile_path#"${repo_path}/profiles/"}
|
|
|
|
# shellcheck disable=SC2034 # it's a reference to external variable
|
|
profile_name_ref="${profile_name}"
|
|
}
|
|
|
|
make_profile_path="${ROOT%/}/etc/portage/make.profile"
|
|
top_profile_dir_path=$(realpath "${make_profile_path}")
|
|
top_repo_path=
|
|
get_repo_from_profile_path "${top_profile_dir_path}" top_repo_path
|
|
top_repo_name=
|
|
repo_path_to_name "${top_repo_path}" top_repo_name
|
|
|
|
if [[ -n ${print_inheritance_tree} ]]; then
|
|
|
|
set -- '0' "${top_repo_name}" "${top_profile_dir_path}"
|
|
|
|
profile_tree=()
|
|
|
|
while [[ ${#} -gt 2 ]]; do
|
|
indent=${1}; shift
|
|
repo_name=${1}; shift
|
|
profile_path=${1}; shift
|
|
|
|
lines=
|
|
fork=
|
|
if [[ ${indent} -gt 0 ]]; then
|
|
if [[ ${indent} -gt 1 ]]; then
|
|
repeat_string '| ' $((indent - 1)) lines
|
|
fi
|
|
fork='+-'
|
|
fi
|
|
g_profile_name=
|
|
get_profile_name "${repo_name}" "${profile_path}" g_profile_name
|
|
profile_tree+=( "${lines}${fork}${repo_name}:${g_profile_name}" )
|
|
g_profile_children=()
|
|
|
|
process_profile "${repo_name}" "${profile_path}" g_profile_children
|
|
|
|
new_profiles=()
|
|
new_indent=$((indent + 1))
|
|
pc_idx=0
|
|
while [[ $((pc_idx + 1)) -lt "${#g_profile_children[@]}" ]]; do
|
|
new_repo_name=${g_profile_children["${pc_idx}"]}
|
|
new_profile_path=${g_profile_children[$((pc_idx + 1))]}
|
|
new_profiles+=( "${new_indent}" "${new_repo_name}" "${new_profile_path}" )
|
|
pc_idx=$((pc_idx + 2))
|
|
done
|
|
|
|
set -- "${new_profiles[@]}" "${@}"
|
|
done
|
|
|
|
if [[ -n ${print_headers} ]]; then
|
|
echo
|
|
echo 'profile inheritance tree:'
|
|
echo
|
|
fi
|
|
for line in "${profile_tree[@]}"; do
|
|
echo "${line}"
|
|
done
|
|
|
|
fi
|
|
|
|
if [[ -n ${print_evaluation_order} ]]; then
|
|
|
|
set -- "${top_repo_name}" "${top_profile_dir_path}" '0'
|
|
|
|
profile_eval=()
|
|
|
|
while [[ ${#} -gt 2 ]]; do
|
|
repo_name=${1}; shift
|
|
profile_path=${1}; shift
|
|
num_parents=${1}; shift
|
|
# each parent is a repo name and profile path, so two items for each parent
|
|
num_parent_items=$((num_parents * 2))
|
|
parents=( "${@:1:${num_parent_items}}" )
|
|
shift "${num_parent_items}"
|
|
g_profile_children=()
|
|
|
|
process_profile "${repo_name}" "${profile_path}" g_profile_children
|
|
|
|
new_args=()
|
|
if [[ ${#g_profile_children[@]} -eq 0 ]]; then
|
|
to_evaluate=( "${repo_name}" "${profile_path}" "${parents[@]}" )
|
|
te_idx=0
|
|
while [[ $((te_idx + 1)) -lt "${#to_evaluate[@]}" ]]; do
|
|
new_repo_name=${to_evaluate["${te_idx}"]}
|
|
new_profile_path=${to_evaluate[$((te_idx + 1))]}
|
|
g_new_profile_name=
|
|
get_profile_name "${new_repo_name}" "${new_profile_path}" g_new_profile_name
|
|
profile_eval+=( "${new_repo_name}:${g_new_profile_name}" )
|
|
te_idx=$((te_idx + 2))
|
|
done
|
|
else
|
|
last_idx=$(( ${#g_profile_children[@]} - 2 ))
|
|
pc_idx=0
|
|
while [[ $((pc_idx + 1)) -lt "${#g_profile_children[@]}" ]]; do
|
|
new_repo_name=${g_profile_children["${pc_idx}"]}
|
|
new_profile_path=${g_profile_children[$((pc_idx + 1))]}
|
|
new_args+=( "${new_repo_name}" "${new_profile_path}" )
|
|
if [[ pc_idx -eq last_idx ]]; then
|
|
new_args+=( $((num_parents + 1)) "${repo_name}" "${profile_path}" "${parents[@]}" )
|
|
else
|
|
new_args+=( 0 )
|
|
fi
|
|
pc_idx=$((pc_idx + 2))
|
|
done
|
|
fi
|
|
|
|
set -- "${new_args[@]}" "${@}"
|
|
done
|
|
|
|
if [[ -n ${print_headers} ]]; then
|
|
echo
|
|
echo 'profile evaluation order:'
|
|
echo
|
|
fi
|
|
for line in "${profile_eval[@]}"; do
|
|
echo "${line}"
|
|
done
|
|
|
|
fi
|