#!/usr/bin/env bash set -uo pipefail readonly cache_dir="${XDG_CACHE_HOME:-${HOME}/.cache}/package-status" readonly cache_file="${cache_dir}/status" readonly attempt_file="${cache_dir}/last-attempt" readonly pacman_log="/var/log/pacman.log" readonly pacman_lock="/var/lib/pacman/db.lck" mkdir -p "${cache_dir}" chmod 700 "${cache_dir}" touch "${attempt_file}" || exit 1 # Never inspect the package database while pacman is changing it. A later # timer run or terminal startup will request another refresh. if [[ -e "${pacman_lock}" ]]; then exit 75 fi pacman_log_signature_before=$(stat -c '%Y:%s:%i' "${pacman_log}" 2>/dev/null || printf '0:0:0') updates_output='' updates_output=$(CHECKUPDATES_DB="${cache_dir}/checkupdates-db" checkupdates --nocolor 2>/dev/null) checkupdates_status=$? case "${checkupdates_status}" in 0) updates_count=$(printf '%s\n' "${updates_output}" | awk 'NF { count++ } END { print count + 0 }') ;; 2) updates_count=0 ;; *) # A network or mirror failure must not replace a known-good cache. exit "${checkupdates_status}" ;; esac orphans_count=$(pacman -Qdtq 2>/dev/null | awk 'NF { count++ } END { print count + 0 }') pacman_log_signature_after=$(stat -c '%Y:%s:%i' "${pacman_log}" 2>/dev/null || printf '0:0:0') # Discard the result if a package operation overlapped this refresh. if [[ -e "${pacman_lock}" || "${pacman_log_signature_before}" != "${pacman_log_signature_after}" ]]; then exit 75 fi umask 077 temporary_file=$(mktemp "${cache_dir}/status.XXXXXX") trap 'rm -f "${temporary_file}"' EXIT printf 'version=1\nupdates=%d\norphans=%d\nchecked_at=%d\npacman_log_signature=%s\n' \ "${updates_count}" \ "${orphans_count}" \ "$(date +%s)" \ "${pacman_log_signature_after}" > "${temporary_file}" mv -f "${temporary_file}" "${cache_file}" trap - EXIT