#!/usr/bin/env bash BOOTSTRAP_DIR=~/.dotfiles/bootstrap OUTPUT=${BOOTSTRAP_DIR}/packages.tsv pkg_all=$(pacman -Qqett | grep -v "$(pacman -Qqg base-devel)") pkg_repo=$(pacman -Qqn) pkg_aur=$(pacman -Qqm) while getopts "nvh" opt; do case "$opt" in n) DRYRUN=true ;; v) VERBOSE=true ;; h | *) { printf "\nUpdate the list of installed packages.\n\nWill compare packages committed to the dotfile repository\nand those currently installed (on an Arch system, using pacman).\nUpdates the list of committed packages in repository\nand prints out the differences as a diff.\n\nOptions:\n\n\t-h\tDisplay this help.\n\t-v\tShow verbose information.\n\t-n\tPrint out changes without changing anything (dry-run).\n" exit 1 } ;; esac done print_msg() { # shellcheck disable=2059 [ -n "$VERBOSE" ] && printf "$@" } # tsv file: # packagename, description, source, target # toot a toot manager A D if [ -f "${OUTPUT}_TEMP" ]; then rm "${OUTPUT}_TEMP" fi touch "${OUTPUT}_TEMP" # create new package list for pkg in $pkg_all; do source="" if echo "$pkg_repo" | grep -F -q -x "$pkg"; then source="R" elif echo "$pkg_aur" | grep -F -q -x "$pkg"; then source="A" else echo "ERROR: The package $pkg could not be found in repositories or AUR." exit 1 fi desc=$(pacman -Qs "$pkg" | grep -A1 --color "local/$pkg\s" | tail -n1) #remove leading whitespace desc="${desc#"${desc%%[![:space:]]*}"}" target="" if [ -f "$OUTPUT" ]; then found_line=$(grep -e "^$pkg" "$OUTPUT") fi if [ -n "$found_line" ]; then target=$(echo "$found_line" | cut -f4) print_msg "Updating pkg: %s:%s from: %s, for: %s\n" "$pkg" "$desc" "$source" "$target" else print_msg "Adding pkg: %s:%s from: %s, for: %s\n" "$pkg" "$desc" "$source" "$target" fi printf "%s\t%s\t%s\t%s\n" "$pkg" "$desc" "$source" "$target" >>"${OUTPUT}_TEMP" done # notify on any removed packages if [ -f "$OUTPUT" ]; then while read -r line; do if ! echo "$line" | cut -f1 | xargs -I _ grep -F -q -x _ <(echo "$pkg_all"); then printf "REMOVED: %s\n" "$line" fi done <<<"$(tail +2 $OUTPUT)" fi # show file changes if [ -f "$OUTPUT" ] && [ -f "$OUTPUT"_TEMP ]; then changes=$(diff --color=always -y --suppress-common-lines "$OUTPUT" "$OUTPUT"_TEMP | tail -n+2) printf "FILE CHANGES:\n=============\n%s" "$changes" fi # actually write to file if [ -z "$DRYRUN" ]; then cat <(printf "Name\tDescription\tSource\tTarget\n") "${OUTPUT}_TEMP" >"$OUTPUT" fi rm "${OUTPUT}_TEMP"