From 0f3c45c1d3b0c198a3fc0f34575f4dc518882625 Mon Sep 17 00:00:00 2001 From: Jan Lindemann Date: Sun, 16 Nov 2025 20:19:32 +0100 Subject: [PATCH] Re-add jw-pkg: Use by many postinstall scripts There's a certain logic that jw-pkg is part of jw-build, because it comes in handy to compile config file templates in a post-install stage. On the other hand, jw-base looks like a better place for that. Re-adding for now, to not break too many packages. Signed-off-by: Jan Lindemann --- scripts/jw-pkg | 503 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 503 insertions(+) create mode 100644 scripts/jw-pkg diff --git a/scripts/jw-pkg b/scripts/jw-pkg new file mode 100644 index 00000000..6afb0759 --- /dev/null +++ b/scripts/jw-pkg @@ -0,0 +1,503 @@ +#!/bin/bash + +log() +{ + if [ "$1" = -n ]; then + shift + echo -n "$myname: $*" + return + fi + + if [ "$1" = -c ]; then + shift + echo "$*" + return + fi + + if [ "$1" = -C ]; then + shift + echo -n "$*" + return + fi + + echo "$myname: $*" +} + +channel_present() +{ + if smart channel --show $1 2>&1 | grep -q baseurl >/dev/null; then + return 0 + fi + return 1 +} + +usage() +{ +cat << EOT + + $myname [global options] command [options] [package ...] + + command is one of + + help: show this help screen + init: initialize + uninit: undo initialization + install: install packages in [arguments] + update: update all jannet software on the system + restore: restore a previous jannet software version state + list: query information about installed software packages + list-projects: query information about installed software projects + checklog: update the installation log file if necessary + rpmnew: remove superfluous rpmnew files and show conflicts + for others + build-date: show installed janware packages along with build date + built-today: show installed janware packages built today + + list-changed-files: list files changed since installation + + list-templates: list templates + list-template-tables: list templates tables + list-template-output: list template output files + rm-template-output: remove template output files + compile-templates: compile templates + + global options are + + -v be verbose + + package + + optional whitespace-separated list of package names, generally limiting the + scope of the command to the specified packages, defaults to all installed + janware packages + +EOT + [ "$1" ] && exit $1 +} + +create_ldconfig_state() +{ + echo "=== automatically created by $myname update script" + echo "--- files" + ls /etc/ld.so.conf.d + echo "--- directories" + find /etc/ld.so.conf.d -type f | xargs cat | sort -u +} + +check_ldconfig() +{ + local state=/var/log/jw-build-ldconf.state + [ -f $state ] && create_ldconfig_state | diff $state - >/dev/null 2>&1 && return + echo -n "running ldconfig ... " + /sbin/ldconfig + create_ldconfig_state > $state + echo "done." +} + +list_packages() +{ + local query_tags="" + + eval set -- `getopt -- VPNUD "$@"` + while [ "$1" != -- ]; do + case $1 in + -V) + query_tags="$query_tags %{Vendor}" + ;; + -P) + query_tags="$query_tags %{Packager}" + ;; + -U) + query_tags="$query_tags %{URL}" + ;; + -D) + query_tags="$query_tags %{Distribution}" + ;; + *) + echo -e "Unexpected argument >$1<\n" >&2 + usage 1 + ;; + esac + shift + done + shift + + [ "$query_tags" ] || query_tags="%{URL}" + + local names="$1" + local rpm_args + if [ -n "$names" ]; then + rpm_args="$rpm_args $names" + else + rpm_args="$rpm_args -a" + fi + rpm -q --queryformat "%{Name}: $query_tags\n" $rpm_args | \ + grep -i '^[^ ]\+:.*\(jannet\|janware\)' | \ + sed 's/\(^[^ ]\+\) *:.*/\1/; s/[ ]*$//' |\ + sort -u +} + +list_projects() +{ + list_packages "$@" | xargs -r rpm -q --queryformat '%{SOURCERPM}\n' | \ + sed 's/[ ]*//; s/-[0-9]\+.*//' |\ + sort -u +} + +list_files() +{ + # Need to sort -u, because apparently, during installation, rpm -ql + # returns every file in the package _twice_. Funny. + list_packages "$@" | sort -u | xargs -r rpm -ql +} + +cmd_rpmnew() +{ + local file + + list_files "$@" | + while read file; do + if [ -e "$file.rpmnew" ]; then + if diff -q $file $file.rpmnew; then + if [ -L "$file" ]; then + echo ========== skipping link $file + diff $file.rpmnew $file + continue + fi + echo mv $file.rpmnew $file + sudo mv $file.rpmnew $file + else + echo =========== $file + diff $file.rpmnew $file + fi + fi + done +} + +cmd_diff() +{ + local file + + list_packages "$@" | + xargs -r rpm -qV | + sed '/^....L\|^..5/ !d; s%[^/]*/%/%' | + while read file; do + if diff -q $file $file.rpmnew; then + if [ -L "$file" ]; then + echo ========== skipping link $file + diff $file.rpmnew $file + continue + fi + echo mv $file.rpmnew $file + sudo mv $file.rpmnew $file + else + echo =========== $file + diff $file.rpmnew $file + fi + done +} + +cmd_build_date() +{ + list_packages "$@" | + xargs -r rpm -q --queryformat '%{BUILDTIME} %{NAME}\n' | + sort -n | + sed 's/-run\|-devel//' | + sort -u | + while read t p; do + echo `date --date=@$t --rfc-3339=seconds` $p + done +} + +cmd_list_templates() +{ + local ext_from="$template_exts" # TODO: support more than one + local ext_from_re=`echo $ext_from | sed 's/\./\\./g'` + local f + + list_files "$@" | while read f; do + [ -f "$f" -o -L "$f" ] || continue + echo $f | grep -q "$ext_from_re$" || continue + echo $f + done +} + +cmd_list_template_tables() +{ + local ext_from="$table_exts" + local e f t + list_files "$@" | while read f; do + [ -f "$f" -o -L "$f" ] || continue + for e in $ext_from; do + t="${f%.*}$e" + [ -f "$t" ] || continue + echo $t + done + done +} + +cmd_list_template_output() +{ + local re=`echo $template_exts | sed 's/\./\\\\./g; s/^ *//; s/ *$//; s/ */$\\\\|/g; s/\(.*\)/\\\\(\1$\\\\)/'` + local f + list_files "$@" | sed "/$re/ !d; s/$re//" | while read f; do + [ -f "$f" -o -L "$f" ] || continue + echo $f + done +} + +cmd_rm_template_output() +{ + local restore=0 + while [ "${1:0:1}" = '-' ]; do + case "$1" in + -r) + restore=1 + ;; + *) + usage 1 + ;; + esac + shift + done + + local f + cmd_list_template_output $@ | while read f; do + log "removing $f" + rm $f + bak=$f$template_bak_ext + if [ "$restore" = 1 -a -f "$bak" ]; then + log "restoring $f from $bak" + mv $bak $f + fi + done +} + +cmd_compile_templates() +{ + __md() { + stat --format '%U:%G %a' "$1" 2>/dev/null + } + + local ext_from="$template_exts" # TODO: support more than one + local ext_from_re=`echo $template_exts | sed 's/\./\\./g'` + local ext_to="" + local ext_tables="$table_exts" + local default_group=root + local default_owner=root + local default_mode=600 + local conf_patt="^[ ]*# *conf:" + local missing_table=0 + local backup=0 + + umask 0077 + + while [ "${1:0:1}" = '-' ]; do + case "$1" in + -o) + default_owner="$2" + shift + ;; + -m) + default_mode="$2" + shift + ;; + -g) + default_group="$2" + shift + ;; + -b) + backup=1 + ;; + -c) + conf_patt="$2" + shift + ;; + *) + usage 1 + ;; + esac + shift + done + + local f + while read f; do + local base=`echo $f | sed "s/$ext_from_re$//"` + [ "$base" ] || continue + local to=$base$ext_to + local table="" + local ext + for ext in $ext_tables; do + table=$base$ext + [ -f "$table" ] && break + done + [ -f $table ] || { + log "WARNING: No key-value table found for template $f, not compiling." >&2 + ((missing_table++)) + continue + } + # TODO: use mktemp -d and keep temporary files in read-only dir + local tmp=$to.tmp + log -n "Applying macros in $table to $f" + local mode=$default_mode + local owner=$default_owner + local group=$default_group + local diff="" + eval `sed "/$conf_patt/ !d; s/$conf_patt//" $f` + eval `sed "/$conf_patt/ !d; s/$conf_patt//" $table` + sed 's|^[ ]*#.*||; s|/|\\/|g; s|\([^ =]\+\)[ =]\+\(.*\)|s/\1/\2/g|' $table | sed -f - $f > $tmp + chmod $mode $tmp + chown $owner $tmp + chgrp $group $tmp + diff -q $tmp $to >/dev/null 2>&1 || diff="@content" + local md_to=$(__md "$to") + local md_tmp=$(__md "$tmp") + [ "$md_to" = "$md_tmp" ] || diff="$diff@metadata ($md_to -> $md_tmp)" + if [ -z "$diff" ]; then + log -c ", no changes." + rm $tmp + continue + fi + local bak=$to$template_bak_ext + if [ "$backup" = 1 -a -f $to ] && ! diff -q $to $bak >/dev/null 2>&1; then + log -C ", saving backup to $to to $bak" + cp -p $to $bak + fi + mv $tmp $to + diff=${diff##@} + log -c ", updating ${diff//@/ + }, done." + done <<< $(cmd_list_templates "$@") + + if [ "$missing_table" != 0 ]; then + log "WARNING: $missing_table missing tables found. You might want to add them and run sudo $cmdline again." + fi +} + +cmd_get_value_from_tables() +{ + local key show_file + eval set -- `getopt -- k: "$@"` + while [ "$1" != -- ]; do + case $1 in + -k) + key=$2 + shift + ;; + -f) + show_file=1 + shift + ;; + *) + echo -e "Unexpected argument >$1<\n" >&2 + usage 1 + ;; + esac + shift + done + shift + + local f + while read f; do + grep -q "^\s*$key\s\+" $f || continue + [ "$show_file" = 1 ] && echo -n "$f: " + sed "s|^[ ]*#.*||; /^\s*$key\(\s\|=\)\+/ !d; s/^\s*$key\(\s\|=\)\+//" $f + done <<< $(cmd_list_template_tables "$@") +} + +cmd_built_today() +{ + local today=`date +'%Y-%m-%d'` + cmd_build_date | grep $today | cut -d' ' -f3 +} + +cmd_list_changed_files() +{ + list_projects "$@" | xargs rpm -qV | grep '^..5' | sed 's|[^/]*/|/|' +} + +# ----- here we go + +cmdline="$0 $@" +myname=`basename $0` +longname=$0 +opts="v" +table_exts=".jw-secret .jw-vars" +template_exts=".jw-tmpl" +template_bak_ext=".jw-pkg.bak" + +while [ "${1:0:1}" = '-' ]; do +case "$1" in +-v) + opt_verbose=true + shift + ;; +*) + usage 1 + ;; +esac +shift +done + +cmd="${1//-/_}" +shift + +case $cmd in + +# -- TODO: re-implement this using pkg-manager.sh, or integrate with pkg-manager.sh +#init) +# if ! channel_present ftp.jannet.de; then +# echo -n "adding installation source ... " +# sudo smart channel -y --add ftp.jannet.de \ +# type=yast2 \ +# baseurl=ftp://dspadm:dspasswd@ftp.jannet.de/pub/packages/linux/suse/10.1 \ +# >/dev/null 2>&1 +# if channel_present; then echo done; else echo failed; fi +# fi +# ;; +# +#uninit) +# if channel_present ftp.jannet.de; then +# echo -n "removing installation source ... " +# sudo smart channel -y --remove ftp.jannet.de >/dev/null 2>&1 +# echo done +# fi +# ;; +# +#update) +# sudo smart update ftp.jannet.de +# sudo smart upgrade -y +# check_ldconfig +# ;; +# +#install) +# sudo smart update ftp.jannet.de +# if [ -f $1 ]; then +# sudo smart install -y `cat $1` +# else +# sudo smart install -y $* +# fi +# check_ldconfig +# ;; +#restore) +# echo "not yet implemented, sorry" >&2 +# ;; +list) + if [ "$opt_verbose" = true ]; then + list_packages "$@" | xargs -r rpm -qi + else + list_packages "$@" | xargs -r rpm -q + fi + ;; +list_projects) + list_projects "$@" + ;; +compile_templates|list_templates|list_template_tables|list_template_output|rm_template_output|diff|build_date|built_today|rpmnew|get_value_from_tables|list_changed_files) + cmd_$cmd "$@" + ;; +help) + usage 0 + ;; +*) + usage 1 + ;; +esac