#!/bin/bash # Backup package-user-dir, update packages, compute diffs. # # Might be worth re-implementing as advice for package.el commands: # would avoid the "sacrificial" Emacs sessions… set -euo pipefail test "${DEBUG:-}" && set -x cd ~/.config/emacs test -L elpa || { echo >&2 "'elpa' directory must be a symlink." exit 1 } OLDELPADIR=$(readlink elpa) NEWELPADIR=.elpa.$(date +%F-%T) read-packages () { local -n pkgarray=$1 local pkgel name version for pkgel in elpa/*/*-pkg.el do # Extract NAME & VERSION out of elpa/NAME-VERSION/NAME-pkg.el. pkgel=${pkgel#elpa/} name=${pkgel} name=${name##*/} name=${name%-pkg.el} version=${pkgel} version=${version%/${name}-pkg.el} version=${version#${name}-} pkgarray[${name}]=${version} done } enum-packages () { IFS=$'\n' eval ' echo "${!OLDPACKAGES[*]}" echo "${!NEWPACKAGES[*]}" ' | sort -u } compare-packages () { local pkg oldv newv while read pkg do oldv=${OLDPACKAGES[${pkg}]:-} newv=${NEWPACKAGES[${pkg}]:-} test "${oldv}" = "${newv}" && # No changes, skip. continue test "${oldv}" -a "${newv}" && # Make a patch for later review. ( set +e diff > ${NEWELPADIR}/update-${pkg}.patch \ -ru ${OLDELPADIR}/${pkg}-${oldv} ${NEWELPADIR}/${pkg}-${newv} diffstatus=$? case ${diffstatus} in 0|1) exit 0 ;; *) exit ${diffstatus} ;; esac ) echo -e "${pkg}\t${oldv:-[NEW]}\t${newv:-[REMOVED]}" done } cp -a ${OLDELPADIR} ${NEWELPADIR} declare -A OLDPACKAGES NEWPACKAGES read-packages OLDPACKAGES ln -fsT ${NEWELPADIR} elpa emacs -f package-upgrade-all -f package-autoremove read-packages NEWPACKAGES enum-packages | compare-packages | column -ts$'\t' | tee ${NEWELPADIR}/update.sum