gentoo-install/scripts/utils.sh

215 lines
4.3 KiB
Bash
Raw Normal View History

2020-01-08 16:21:01 -01:00
source "$GENTOO_INSTALL_REPO_DIR/scripts/protection.sh" || exit 1
elog() {
echo " * $*"
}
einfo() {
echo " * $*"
}
ewarn() {
echo " * $*" >&2
}
eerror() {
echo " * ERROR: $*" >&2
}
die() {
eerror "$*"
kill "$GENTOO_INSTALL_REPO_SCRIPT_PID"
exit 1
}
# Prints an error with file:line info of the nth "stack frame".
# 0 is this function, 1 the calling function, 2 its parent, and so on.
die_trace() {
local idx="${1:-0}"
shift
echo "${BASH_SOURCE[$((idx + 1))]}:${BASH_LINENO[$idx]}: error: ${FUNCNAME[$idx]}: $*" >&2
exit 1
}
for_line_in() {
while IFS="" read -r line || [[ -n $line ]]; do
"$2" "$line"
done <"$1"
}
2020-01-04 10:55:31 -01:00
flush_stdin() {
local empty_stdin
while read -r -t 0.01 empty_stdin; do true; done
2020-01-04 10:55:31 -01:00
}
2020-01-04 10:55:31 -01:00
ask() {
local response
while true; do
2020-01-04 10:55:31 -01:00
flush_stdin
2020-01-04 11:09:29 -01:00
read -r -p "$* (Y/n) " response \
|| die "Error in read"
case "${response,,}" in
'') return 0 ;;
y|yes) return 0 ;;
n|no) return 1 ;;
*) continue ;;
esac
done
}
2020-01-04 10:55:31 -01:00
try() {
local response
local cmd_status
2020-01-04 11:09:29 -01:00
local prompt_parens="(Shell/retry/abort/continue/print)"
2020-01-04 10:55:31 -01:00
# Outer loop, allows us to retry the command
while true; do
# Try command
"$@"
cmd_status="$?"
if [[ $cmd_status != 0 ]]; then
echo " * Command failed: \$ $*"
echo "Last command failed with exit code $cmd_status"
2020-01-04 10:55:31 -01:00
# Prompt until input is valid
while true; do
echo -n "Specify next action $prompt_parens "
2020-01-04 10:55:31 -01:00
flush_stdin
2020-01-04 11:09:29 -01:00
read -r response \
|| die "Error in read"
2020-01-04 10:55:31 -01:00
case "${response,,}" in
''|s|shell)
echo "You will be prompted for action again after exiting this shell."
/bin/bash --init-file <(echo "init_bash")
2020-01-04 10:55:31 -01:00
;;
r|retry) continue 2 ;;
2020-01-04 11:09:29 -01:00
a|abort) die "Installation aborted" ;;
c|continue) return 0 ;;
p|print) echo "\$ $*" ;;
2020-01-04 11:31:39 -01:00
*) ;;
2020-01-04 10:55:31 -01:00
esac
done
fi
return
2020-01-04 10:55:31 -01:00
done
}
countdown() {
echo -n "$1" >&2
local i="$2"
while [[ $i -gt 0 ]]; do
echo -n "$i " >&2
i=$((i - 1))
sleep 1
done
echo >&2
}
download_stdout() {
wget --quiet --https-only --secure-protocol=PFS -O - -- "$1"
}
download() {
wget --quiet --https-only --secure-protocol=PFS --show-progress -O "$2" -- "$1"
}
2020-04-21 18:58:21 +00:00
get_device_by_blkid_field() {
local blkid_field="$1"
local field_value="$2"
blkid -g \
|| die "Error while executing blkid"
local dev
2020-04-21 18:58:21 +00:00
dev="$(blkid -o export -t "$blkid_field=$field_value")" \
|| die "Error while executing blkid to find $blkid_field=$field_value"
dev="$(grep DEVNAME <<< "$dev")" \
|| die "Could not find DEVNAME=... in blkid output"
dev="${dev:8}"
echo -n "$dev"
}
2020-04-21 18:58:21 +00:00
get_device_by_partuuid() {
get_device_by_blkid_field 'PARTUUID' "$1"
}
get_device_by_ptuuid() {
get_device_by_blkid_field 'PTUUID' "$1"
}
get_device_by_uuid() {
2020-04-21 18:58:21 +00:00
get_device_by_blkid_field 'UUID' "$1"
}
load_or_generate_uuid() {
local uuid
local uuid_file="$UUID_STORAGE_DIR/$1"
if [[ -e $uuid_file ]]; then
uuid="$(cat "$uuid_file")"
else
uuid="$(uuidgen -r)"
mkdir -p "$UUID_STORAGE_DIR"
echo -n "$uuid" > "$uuid_file"
fi
echo -n "$uuid"
}
# Parses named arguments and stores them in the associative array `arguments`.
# If given, the associative array `known_arguments` must contain a list of arguments
# prefixed with + (mandatory) or ? (optional). "at least one of" can be expressed by +a|b|c.
parse_arguments() {
local key
local value
local a
for a in "$@"; do
key="${a%%=*}"
value="${a#*=}"
2020-04-21 19:52:46 +00:00
2020-04-21 20:04:39 +00:00
if [[ $key == "$a" ]]; then
2020-04-21 19:52:46 +00:00
extra_arguments+=("$a")
continue
fi
arguments[$key]="$value"
done
declare -A allowed_keys
if [[ -v known_arguments ]]; then
local m
for m in "${known_arguments[@]}"; do
case "${m:0:1}" in
'+')
m="${m:1}"
local has_opt=false
local m_opt
# Splitting is intentional here
# shellcheck disable=SC2086
for m_opt in ${m//|/ }; do
allowed_keys[$m_opt]=true
if [[ -v arguments[$m_opt] ]]; then
has_opt=true
fi
done
[[ $has_opt == true ]] \
|| die_trace 2 "Missing mandatory argument $m=..."
;;
'?')
allowed_keys[${m:1}]=true
;;
*) die_trace 2 "Invalid start character in known_arguments, in argument '$m'" ;;
esac
done
for a in "${!arguments[@]}"; do
[[ -v allowed_keys[$a] ]] \
|| die_trace 2 "Unkown argument '$a'"
done
fi
}