#!/bin/sh # Check repository for outdated packages repology_version() { # Grab the package's version as known by repology.org by downloading the # svg latest-version badge and extracting the version from the xml. repology_name "$1" r=$(curl -Ss "https://repology.org/badge/latest-versions/$remote.svg") && { remote_ver=${r%*} remote_ver=${remote_ver##*>} } } repology_name() { # Fix any known naming inconsistences between packages and Repology. remote=$( # Strip unrelated suffixes. remote=${1%%-bin} remote=${remote%%-git} printf %s "$remote" | # Remote names are all lowercase. tr '[:upper:]' '[:lower:]' | # Remote always uses -. tr _ - ) case $remote in baseinit|baselayout|kiss) remote=- ;; clang) remote=llvm ;; dash) remote=dash-shell ;; dejavu-ttf) remote=fonts:dejavu ;; dsp) remote=dsp-audio-processing ;; emacs-nox) # TODO [community]: Make default emacs no x11? remote=emacs ;; fd) remote=fd-find ;; fetsh) # TODO [community]: Rename package? remote=fet.sh ;; firefox-esr) remote=firefox ;; font-awesome-ttf) remote=fonts:fontawesome ;; gc) remote=boehm-gc ;; gnugrep) # shell-check is dumb here so this must be quoted. remote='grep' ;; gnupg[12]) # Reported to repology.org. # https://github.com/repology/repology-rules/issues/285 remote=gnupg ;; gtk+3) remote=gtk3+classic ;; gst-*) remote=gstreamer:${remote##*-} ;; gtar) remote=tar ;; eiwd) remote=iwd ;; hack) # It might be nice to adopt Repology's naming scheme for # fonts as it also makes them self-documenting and easy # to search for ('kiss s font:\*). remote=fonts:hack ;; harfbuzz-icu) # TODO: Report to repology.org? # Package split. remote=harfbuzz ;; libelf) remote=elfutils ;; liberation-fonts) remote=fonts:liberation ;; libmupdf | libxaw3d) # TODO [community]: Rename packages? remote=${remote##lib} ;; links2) # TODO [community]: Rename package? remote=links ;; linux-headers) remote=linux ;; lux) remote=lux-brightness-ventto ;; man-pages) # TODO: Report to repology.org. # man-pages -> manpages # man-pages-posix -> man-pages-posix remote=manpages ;; netsurf-fb) remote=netsurf ;; openjpeg2) # TODO [community]: Rename package? remote=openjpeg ;; osh) remote=oil-shell ;; pinentry-dmenu) remote=pinentry-dmenu-cemkeylan ;; pyqt5) # TODO [community]: Rename package? remote=python-qt ;; python2) remote=python ;; qt5*) remote=qt ;; rage) remote=rage-encryption-tool ;; sane) remote=sane-backends ;; spleen-font) remote=fonts:spleen ;; sshfs) remote=fusefs:sshfs ;; surf) remote=surf-browser ;; st) remote=st-term ;; terminus-font) remote=fonts:terminus ;; tiv) remote=tiv-unclassified ;; unifont) remote=fonts:unifont ;; webkit2gtk) # TODO [community]: Rename package? remote=webkitgtk ;; xf86-*) remote=xdrv:${remote##*-} ;; xmlsec1) # TODO [community]: Rename package? remote=xmlsec ;; esac } main() { printf '\n[Checking Repology for outdated packages in %s]\n\n' "${1%%/}" >&2 for pkg in */; do pkg=${pkg%%/} read -r ver _ 2>/dev/null < "$pkg/version" || { printf '%-30s local version not found\n' "$pkg" >&2 continue } [ "$ver" = git ] && continue repology_version "$pkg" || { printf '%-30s network error\n' "$pkg" >&2 continue } case $remote_ver in *", $ver"* | *"$ver,"* | "$ver") # Package up-to-date, do nothing. ;; '' | ' ') printf '\n%s: empty response\n' "$pkg" >&2 printf 'possible causes:\n' >&2 printf ' package name differs from repology name,\n' >&2 printf ' package not tracked by repology,\n' >&2 printf ' network error\n\n' >&2 ;; '-') # No version scheme, do nothing. ;; *) printf '%-30s %s -> %s\n' "$pkg" "$ver" "$remote_ver" ;; esac done } for repo do [ "$repo" ] || { printf 'usage: kiss outdated /path/to/repo\n' >&2 exit 1 } cd "$repo" 2>/dev/null || { printf 'repository %s is inaccessible\n' "$repo" >&2 exit 1 } main "$repo" cd "$OLDPWD" || exit 1 done