File fix-home-kimi-source-and-key of Package kimi-utils-ubuntu

#!/usr/bin/bash
# -*- mode: Shell-script; sh_shell: "bash"; -*-

set -euo pipefail
IFS=$'\n\t'
LANG=C

SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
source /etc/os-release

if [ "$EUID" -ne 0 ]; then
    echo "Please run as root"
    exit 1
fi

KEYRING_DIR="/usr/share/keyrings"
KEYFILE_NAME="home_kimi.gpg"
KEYFILE="${KEYRING_DIR}/${KEYFILE_NAME}"
REPO_URL="http://download.opensuse.org/repositories/home:/kimi:/utils/xUbuntu_${VERSION_ID}"
KEY_URL="${REPO_URL}/Release.key"
SRC_GLOB="/etc/apt/sources.list.d/home:kimi:*.list"
ENABLE_BACKUP=0

# track deleted/rotated files for reporting
DELETED=()
ROTATED=()

die() { printf 'Error: %s\n' "$*" >&2; exit 1; }
log_info() { printf 'Info: %s\n' "$*"; }
log_warn() { printf 'Warning: %s\n' "$*"; }

safe_mv() {
    local src=$1 dst=$2
    if [[ -e "$src" ]]; then
        if mv -v -- "$src" "$dst"; then
            ROTATED+=("$src -> $dst")
        else
            log_warn "mv failed: $src -> $dst"
        fi
    else
        log_info "source not found, skipping mv: $src"
    fi
}

safe_rm() {
    for f in "$@"; do
        [[ -e "$f" ]] || continue
        if rm -f -- "$f"; then
            DELETED+=("$f")
        else
            log_warn "rm failed: $f"
        fi
    done
}

set_key_permissions() {
    if [[ -f "$KEYFILE" ]]; then
        chmod 0644 "$KEYFILE" || log_warn "chmod failed on $KEYFILE"
        chown root:root "$KEYFILE" || log_warn "chown failed on $KEYFILE"
        echo "Permissions set on $KEYFILE"
    else
        log_info "No key file to set permissions on: $KEYFILE"
    fi
}

rename_expired_key() {
    local file=$1 base ts new
    base="${file%~}"
    ts=$(date '+.%Y-%m-%d_%H-%M-%S')
    new="${base}${ts}~"
    echo "Renaming expired $file → $new"
    safe_mv "$file" "$new"
}

mkdir -p "$KEYRING_DIR"

shopt -s nullglob
found=()
for d in /etc/apt/trusted.gpg.d /etc/apt/keyrings /usr/share/keyrings; do
    found+=("$d"/home_kimi*)
done
shopt -u nullglob

for f in "${found[@]}"; do
    [[ -f "$f" && ! -s "$f" ]] && echo "Removing empty $f" && rm -f "$f" && DELETED+=("$f")
done

found=()
shopt -s nullglob
for d in /etc/apt/trusted.gpg.d /etc/apt/keyrings /usr/share/keyrings; do
    found+=("$d"/home_kimi*)
done
shopt -u nullglob

if ((${#found[@]})); then
    echo "Found ${#found[@]} home_kimi key(s):"
    printf '  %s\n' "${found[@]}"

    for f in "${found[@]}"; do
        if gpg --show-key --with-colons "$f" 2>/dev/null |
            awk -F: '$1=="pub"{print $7}' |
            while read -r exp; do
                [[ -z "$exp" ]] && echo "no-expiry" && exit 0
                ((exp < $(date +%s))) && echo "expired" && exit 0
            done | grep -qE 'expired|no-expiry'; then
            rename_expired_key "$f"
        fi
    done

    found=()
    shopt -s nullglob
    for d in /etc/apt/trusted.gpg.d /etc/apt/keyrings /usr/share/keyrings; do
        found+=("$d"/home_kimi*)
    done
    shopt -u nullglob

    for f in "${found[@]}"; do
        [[ -e "$f" ]] || continue
        src=$(readlink -f "$f")
        dest=$(readlink -f "$KEYRING_DIR/${f##*/}")

        if [[ "$src" == "$dest" ]]; then
            echo "Already in $KEYRING_DIR: $f"
            continue
        fi
        echo "Moving $f → $KEYRING_DIR/"
        safe_mv "$f" "$KEYRING_DIR/"
    done
else
    echo "No existing home_kimi keys found."
fi

shopt -s nullglob
keys=("$KEYRING_DIR"/home_kimi*.gpg)
shopt -u nullglob

if ((${#keys[@]} > 1)); then
    newest=""
    newest_exp=0

    get_expiry() {
        gpg --show-key --with-colons "$1" 2>/dev/null |
            awk -F: '$1=="pub"{print $7}' | head -n1
    }

    for k in "${keys[@]}"; do
        exp=$(get_expiry "$k")
        exp=${exp:-0}
        ((exp == 0)) && exp=$(stat -c %Y "$k" 2>/dev/null || stat -f %m "$k")
        ((exp > newest_exp)) && newest_exp=$exp && newest=$k
    done

    echo "Keeping newest key: ${newest:-<none>}"

    if [[ -n "$newest" ]]; then
        newest_real=$(readlink -f "$newest" 2>/dev/null || echo "$newest")
        keyfile_real=$(readlink -f "$KEYFILE" 2>/dev/null || echo "$KEYFILE")

        if [[ "$newest_real" == "$keyfile_real" ]]; then
            log_info "Newest key is already the canonical key; no move needed."
        else
            if [[ -f "$KEYFILE" ]]; then
                dest="${KEYFILE}.$(date '+%Y-%m-%d_%H-%M-%S')~"
                if mv -v -- "$KEYFILE" "$dest"; then
                    ROTATED+=("$KEYFILE -> $dest")
                else
                    log_warn "Failed to rotate canonical key $KEYFILE"
                fi
            else
                log_info "Canonical key not present; skipping rotation"
            fi

            if [[ -f "$newest" ]]; then
                if mv -v -- "$newest" "$KEYFILE"; then
                    ROTATED+=("$newest -> $KEYFILE")
                else
                    log_warn "Failed to move newest $newest to $KEYFILE"
                fi
            else
                log_warn "Expected newest key file missing: $newest"
            fi
        fi
    else
        log_warn "No newest key determined"
    fi

    shopt -s nullglob
    keys_after=("$KEYRING_DIR"/home_kimi*.gpg)
    shopt -u nullglob
    for k in "${keys_after[@]}"; do
        if [[ "$k" != "$KEYFILE" ]]; then
            safe_rm "$k"
        fi
    done
fi

need_download=1
if [[ -f "$KEYFILE" ]] && /usr/local/bin/check-apt-key-if-less-than-x-days-to-expiry "$KEYFILE"; then
    need_download=0
    echo "Existing key still valid."
fi

if ((need_download)); then
    echo "Downloading key from $KEY_URL"
    if wget -qO- "$KEY_URL" | gpg --dearmor >"$KEYFILE".new; then
        if mv -f -- "$KEYFILE".new "$KEYFILE"; then
            ROTATED+=("$KEYFILE.new -> $KEYFILE")
        else
            log_warn "mv failed moving downloaded key into place"
            safe_mv "$KEYFILE".new "$KEYFILE"
        fi
        set_key_permissions
    else
        rm -f -- "$KEYFILE".new 2>/dev/null || true
        die "Failed to download/dearmor key"
    fi
else
    set_key_permissions
fi

shopt -s nullglob
src_files=($SRC_GLOB)
shopt -u nullglob

if ((${#src_files[@]} == 0)); then
    echo "No home:kimi source‑list files found."
    exit 0
fi

for f in "${src_files[@]}"; do
    ((ENABLE_BACKUP)) && cp -a -- "$f" "${f}.orig" && echo "Backup: ${f}.orig"
    if grep -q "signed-by=${KEYFILE}" "$f"; then
        echo "signed‑by already present in $f"
        continue
    fi

    {
        while IFS= read -r line; do
            if [[ $line =~ ^[[:space:]]*deb[[:space:]]+ ]]; then
                if [[ $line =~ ^([[:space:]]*deb[[:space:]]+)(\[[^]]*\])?[[:space:]]*([^[:space:]]+)([[:space:]].*)$ ]]; then
                    prefix="${BASH_REMATCH[1]}"
                    opts="${BASH_REMATCH[2]}"
                    url="${BASH_REMATCH[3]}"
                    rest="${BASH_REMATCH[4]}"

                    if [[ "$url" =~ ^https?://download\.opensuse\.org/repositories/home:/kimi: ]]; then
                        if [[ -n $opts ]]; then
                            new_opts="${opts%]}"
                            new_opts="${new_opts} signed-by=${KEYFILE}]"
                        else
                            new_opts="[signed-by=${KEYFILE}]"
                        fi
                        echo "${prefix}${new_opts} ${url}${rest}"
                        continue
                    fi
                fi
            fi
            echo "$line"
        done <"$f"
    } >"${f}.tmp" && mv -f "${f}.tmp" "$f"
    echo "Updated signed‑by in $f"
done

echo "Cleaning APT cache ..."
apt clean || log_warn "apt clean failed"
rm -rf /var/lib/apt/lists/* || log_warn "rm lists failed"

echo
echo "Key file:"
ls -al "$KEYFILE" 2>/dev/null || echo "(no keyfile found: $KEYFILE)"
echo

echo "Updated source‑list files:"
for f in "${src_files[@]}"; do
    echo "---- $f ----"
    grep -E '^deb' "$f" || echo "(no deb line found)"
done

# Only print a summary if there were changes
if ((${#ROTATED[@]} + ${#DELETED[@]})); then
    echo
    echo "Summary of changes:"
    if ((${#ROTATED[@]})); then
        echo "Rotated/moved files:"
        for r in "${ROTATED[@]}"; do echo "  $r"; done
    fi
    if ((${#DELETED[@]})); then
        echo "Deleted files:"
        for d in "${DELETED[@]}"; do echo "  $d"; done
    fi
fi

echo "Done."
openSUSE Build Service is sponsored by