t2sde/scripts/Emerge-Pkg
2025-04-18 12:50:28 +00:00

387 lines
9.2 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# --- T2-COPYRIGHT-BEGIN ---
# t2/scripts/Emerge-Pkg
# Copyright (C) 2004 - 2025 The T2 SDE Project
# Copyright (C) 2004 - 2006 Rene Rebe <rene@exactcode.de>
# SPDX-License-Identifier: GPL-2.0
# --- T2-COPYRIGHT-END ---
exec 2>&1
options=
dloptions=
config='default'
deps='indirect2'
debug=0
downloadonly=0
verbose=1
ignore_chksum=1
backup=1
dryrun=0
force=0
rebuild=1
repositories=
system=
depth=0
missing='only'
optional='ask'
maxdepth=9
deptree=
esttime=0
#
# ---- Functions
#
. scripts/functions.in
help_msg() {
local spacer=" "
echo
echo "Usage: Emerge-Pkg [ -cfg <config> ] [ -dry-run ] [ -force ] [ -nobackup ]"
echo "$spacer [ -consider-chksum ] [ -norebuild ] [ -deps=none|fast|indirect ]"
echo "$spacer [ -missing=yes|no|only ] [ -optional-deps=yes|no|ask ] [ -download ]"
echo "$spacer [ -system | -repository repo | repo/* | CV-GROUPs | pkgs ]"
echo
}
#
# ---- Parse options + config
#
if [ $# = 0 ]; then
help_msg
exit 1
fi
while [ "$1" ]; do
case "$1" in
-cfg) options="$options $1 $2" config="$2"; shift ;;
-deps=*) deps=${1/-deps=/} ;;
-missing=*) missing=${1/-missing=/} ;;
-optional-deps=*) optional=${1/-optional-deps=/} ;;
-dry-run) dryrun=1 ;;
-f|-force) force=1 ;;
-debug) debug=1 ;;
-nobackup) backup=0 ;;
-consider-chksum) ignore_chksum=0 ;;
-norebuild) rebuild=0 ;;
-download|-download-only) downloadonly=1 ;;
-repository) repositories="$repositories $2"; shift ;;
-prefix) options="$options -prefix $2"; shift ;;
-v) options="$options -v" ;;
-noclearsrc) options="$options -noclearsrc" ;;
-xtrace) options="$options -xtrace" ;;
-system) system=1 deps=none ;;
-*) help_msg; exit 1 ;;
*/\*) repositories="$repositories ${1%/*}" ;;
*) break ;;
esac
shift
done
case "$deps" in
fast|indirect*|none) : ;;
*)
echo "Unknown dependency resolution mode. Valid are none, fast and indirect."
exit 1
esac
if [ ! -f config/$config/config -a $config = "default" ]; then
scripts/Config -oldconfig
fi
. scripts/parse-config
noautolist=" 00-dirtree $SDECFG_DEFAULT_CC $SDECFG_LIBC ${SDECFG_LIBC}32 "
declare -A packages
declare -A alternatives
declare -A deplist
read_packages() {
local sel pkg _
while read sel _ _ _ pkg _; do
packages[$pkg]=$sel
done < <(cat config/$config/packages)
}
read_alternatives() {
local pkg alt
while read pkg alt; do
alternatives[$pkg]=$alt
done < <(cat misc/share/PKG-ALTERNATIVES)
}
add_if_req() {
local pkg=$1 msg="$2" typ=$3
local buildtime=$(pkgbuildtime $pkg)
[ "$verbose" = 1 ] && echo -n "$msg"
# some more check for packages not manually specified
if [ $depth != 0 ]; then
# no auto update list
if [ "$noautolist" != "${noautolist/ $pkg /}" ]; then
[ $verbose = 1 ] && echo " Vital, skipped by default."
return
fi
fi
if [ $depth -gt 0 ]; then
# optional dep, not yet installed?
if [ "$typ" = '[OPT]' ]; then
if [ "$optional" = ask ]; then
echo -n " Add optional dep? (y/N$(fmt_time $buildtime)) "
read in
# force further updates? TODO: limit input validation
[[ "$in" = *\* ]] && optional=$in
else
in="$optional"
[[ "$in" = y* ]] &&
echo " Optional added. $(fmt_time $buildtime)" ||
echo " Optional, skipped."
fi
if [[ "$in" = y* ]]; then
deplist[$pkg]=y
esttime=$((esttime + buildtime))
[ "$deps" = indirect ] && dep4pkg "$pkg"
[ "$deps" = indirect2 -a $depth -le $maxdepth ] && dep4pkg "$pkg"
else
deplist[$pkg]=o
fi
return
fi
# missing ones? yes, no, only TODO: maybe delete
if [ ! -f /var/adm/packages/$pkg ] ||
grep -a -q '\[BUILDTIME\] .* ERROR' /var/adm/cache/$pkg 2>/dev/null; then
if [ "$missing" = 'no' ]; then
[ $verbose = 1 ] && echo " Not missing, skipped."
return
fi
elif [ "$missing" = 'only' ]; then
[ $verbose = 1 ] && echo " Only missing selected, skipped."
return
fi
fi
[ $verbose = 1 ] && echo " Added.$(fmt_time $buildtime)"
deplist[$pkg]=y
esttime=$((esttime + buildtime))
[ "$deps" = indirect ] && dep4pkg "$pkg"
[ "$deps" = indirect2 -a $depth -le $maxdepth ] && dep4pkg "$pkg"
}
add_if_updated() {
local pkg=$1
local typ=$2
local scanned=${deplist[$pkg]}
if [ "$scanned" ]; then
[ $debug = 1 ] && echo "already been at $pkg ..."
# if prevously only an unselected opt dep, re-check if hard dep now
[ "$scanned" = o -a "$typ" != "[OPT]" ] || return
else
deplist[$pkg]=n # not yet, but been here marker
fi
# read in pkg list?
[ ${#packages[@]} = 0 ] && read_packages && read_alternatives
[ $verbose = 1 ] && echo -n "$deptree$pkg:"
confdir=
for x in package/*/$pkg/$pkg.desc; do
if [ -f "$x" ]; then
if [ "$confdir" ]; then
echo " Warning: Package in multiple trees! Skipped."
return
fi
confdir=${x/$pkg.desc/}
fi
done
if [ -z "$confdir" ]; then
if [ $depth = 0 ]; then
# is it a CV-GROUP?
local pkgs=$(grep "^\[CV-GROUP\] $pkg" package/*/*/*.desc | cut -d / -f 3)
if [ "$pkgs" ]; then
for p in $pkgs; do add_if_updated $p; done
return
fi
local pkg="$(pkgsimilar $pkg)"
if [ "$pkg" ]; then
echo " Error: No such package. Did you mean: $pkg?"
else
echo " Error: No such package."
fi
exit 1
else
echo " Warning: No such package."
return
fi
fi
# TODO: keep unselected in the config, to avoid re-config for masked pkgs
if [ -z "${packages[$pkg]}" ]; then
if [ $depth = 0 ]; then
local desc=$(echo package/*/$pkg/$pkg.desc)
if [ -e "$desc" ]; then
echo " Package not cached, re-reading config:"
scripts/Config -oldconfig -cfg $config
read_packages
fi
if [ -z "${packages[$pkg]}" ]; then
echo " Error: No such package."
exit 1
fi
else
echo " Warning: No such package."
return
fi
fi
if [ "${packages[$pkg]}" != X ]; then
# switch to alternative pkg, if selected
local alt="${alternatives[$pkg]}"
if [ "$alt" ] && [ "${packages[$alt]}" = X ]; then
echo -ne "\b($alt):"
pkg=$alt
confdir=package/*/$pkg
else
echo " Not selected."
return
fi
fi
if [ ! -f /var/adm/packages/$pkg ]; then
if [ "$typ" = "[OPT]" ]; then
add_if_req $pkg ' Not installed.' $typ
else
add_if_req $pkg ' Not installed.'
fi
return
fi
o_ver=$(grep -a '^Package Name and Version' \
/var/adm/packages/$pkg | cut -f6 -d' ')
# we avoid parse_desc here, because it is ~50x slower
n_ver=$(grep -a '^\[V\] ' $confdir/$pkg.desc \
architecture/$SDECFG_ARCH/package/$pkg/$pkg.desc \
target/$SDECFG_TARGET/package/$pkg/$pkg.desc \
2> /dev/null | cut -f2 -d' ' | tail -n 1)
if [ "$o_ver" != "$n_ver" -a "$n_ver" != "0000" ]; then
add_if_req $pkg " New version ($o_ver -> $n_ver)."
return
fi
o_ck=$(grep -a '^\(ROCK Linux\|T2\) Package Source Checksum' \
/var/adm/packages/$pkg | sed 's,.*: ,,')
n_ck=$(pkgchksum package/*/$pkg)
if [ $ignore_chksum = 0 -a "$o_ck" != "$n_ck" ]; then
add_if_req $pkg " New source checksum."
return
fi
if [ -f /var/adm/cache/$pkg ] &&
grep -a -q '\[BUILDTIME\] .* ERROR' /var/adm/cache/$pkg; then
[ $verbose = 1 ] && echo -n " Former build was broken."
if [ $rebuild = 1 ]; then
add_if_req $pkg
else
[ $verbose = 1 ] && echo " Skipped."
fi
return
fi
if [ $force = 1 -a $depth = 0 ]; then
add_if_req $pkg ' Build forced.'
return
fi
if [ $debug = 1 ]; then
echo " Installed and up-to-date."
else
echo -ne \
"\r \r"
fi
}
dep4pkg() {
((depth++))
local _deptree="$deptree"
deptree="$deptree$1|"
local IFS=$'\n'
for dep in `grep -a '\[\(DEP\|OPT\)\]' package/*/$1/$1.cache 2>/dev/null`; do
add_if_updated ${dep#* } ${dep% *}
done
deptree="$_deptree"
((depth--))
}
# the remaining arguments are packages to be built
for pkg in $*; do
[ "${deplist[$pkg]}" != y ] && unset deplist[$pkg];
add_if_updated $pkg
done
# packages from repositories
for x in $repositories; do
for pkg in `egrep -a "^X .* $x .*" config/$config/packages |
cut -d ' ' -f 5`; do
add_if_updated $pkg
done
done
# all installed packages if a system update
if [ "$system" ]; then
depth=-1
for pkg in `cd /var/adm/packages/; ls *`; do
add_if_updated $pkg
done
depth=0
fi
# deplist is unsorted: remove unselected and sort by priority
for pkg in ${!deplist[@]}; do [ ${deplist[$pkg]} != y ] && unset deplist[$pkg]; done
deplist=${!deplist[@]}
deplist=$(grep -a "^. .* .* .* \\(${deplist// /\\|}\\) " config/$config/packages |
sort -k 3 | cut -d ' ' -f 5 | tr '\n' ' ')
if [ "$deplist" ]; then
echo "$(echo "$deplist" |
wc -w) packages scheduled to build$(fmt_time $esttime): $deplist" | fold -s
echo
else
echo "No package scheduled to build."
fi
[ $dryrun = 1 ] && exit
[ $backup = 1 ] && options="$options -update"
i=0
pkgs=$(echo "$deplist" | wc -w)
for pkg in $deplist; do
if scripts/Download -cfg $config $dloptions $pkg; then
if [ $downloadonly != 1 ] &&
! scripts/Build-Pkg $options -progress $((++i))/$pkgs $pkg; then
if [ $SDECFG_CONTINUE_ON_ERROR_AFTER -gt 8 ]; then
echo "Aborting further builds due to config setting CONTINUE_ON_ERROR_AFTER."
exit 1
fi
fi
else
echo "The download for package $pkg failed!"
#exit 1
fi
[ "${dloptions/-quiet-mirror/}" = "$dloptions" ] &&
var_append dloptions ' ' -quiet-mirror
done