emacs-update-packages (2047B)
1 #!/bin/bash 2 3 # Backup package-user-dir, update packages, compute diffs. 4 # 5 # Might be worth re-implementing as advice for package.el commands: 6 # would avoid the "sacrificial" Emacs sessionsโฆ 7 8 set -euo pipefail 9 test "${DEBUG:-}" && set -x 10 11 cd ~/.config/emacs 12 13 test -L elpa || { 14 echo >&2 "'elpa' directory must be a symlink." 15 exit 1 16 } 17 18 OLDELPADIR=$(readlink elpa) 19 NEWELPADIR=.elpa.$(date +%F-%T) 20 21 read-packages () 22 { 23 local -n pkgarray=$1 24 25 local pkgel name version 26 for pkgel in elpa/*/*-pkg.el 27 do 28 # Extract NAME & VERSION out of elpa/NAME-VERSION/NAME-pkg.el. 29 pkgel=${pkgel#elpa/} 30 31 name=${pkgel} 32 name=${name##*/} 33 name=${name%-pkg.el} 34 35 version=${pkgel} 36 version=${version%/${name}-pkg.el} 37 version=${version#${name}-} 38 39 pkgarray[${name}]=${version} 40 done 41 } 42 43 enum-packages () 44 { 45 IFS=$'\n' eval ' 46 echo "${!OLDPACKAGES[*]}" 47 echo "${!NEWPACKAGES[*]}" 48 ' | sort -u 49 } 50 51 compare-packages () 52 { 53 local pkg oldv newv 54 55 while read pkg 56 do 57 oldv=${OLDPACKAGES[${pkg}]:-} 58 newv=${NEWPACKAGES[${pkg}]:-} 59 60 test "${oldv}" = "${newv}" && 61 # No changes, skip. 62 continue 63 64 test "${oldv}" -a "${newv}" && 65 # Make a patch for later review. 66 ( 67 set +e 68 diff > ${NEWELPADIR}/update-${pkg}.patch \ 69 -ru ${OLDELPADIR}/${pkg}-${oldv} ${NEWELPADIR}/${pkg}-${newv} 70 71 72 diffstatus=$? 73 case ${diffstatus} 74 in 75 0|1) exit 0 ;; 76 *) exit ${diffstatus} ;; 77 esac 78 ) 79 80 echo -e "${pkg}\t${oldv:-[NEW]}\t${newv:-[REMOVED]}" 81 done 82 } 83 84 cp -a ${OLDELPADIR} ${NEWELPADIR} 85 86 declare -A OLDPACKAGES NEWPACKAGES 87 88 read-packages OLDPACKAGES 89 ln -fsT ${NEWELPADIR} elpa 90 91 emacs -f package-upgrade-all -f package-autoremove 92 read-packages NEWPACKAGES 93 94 enum-packages | compare-packages | column -ts$'\t' | 95 tee ${NEWELPADIR}/update.sum