#!/usr/bin/env bash BOOTSTRAP_DIR=${BOOTSTRAP_DIR:-$(pwd)/bootstrap} INPUTFILES=$(find "${BOOTSTRAP_DIR}" -type f -name 'packages*.tsv') OUTPUTFILE=${BOOTSTRAP_DIR}/packages_testing.tsv pkg_all=$(pacman -Qqett) pkg_repo=$(pacman -Qqn) pkg_aur=$(pacman -Qqm) while getopts "nvhf:" opt; do case "$opt" in n) DRYRUN=true ;; v) VERBOSE=true ;; f) OUTPUTFILE="$OPTARG" ;; 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 # get all existing written packages if [ -n "$INPUTFILES" ]; then INPUT=$(cat $INPUTFILES | grep -v -e '^Name Description Source Target' | sort) else INPUT="" fi print_msg() { # shellcheck disable=2059 [ -n "$VERBOSE" ] && printf "$@" } # tsv file: # packagename, description, source, target # toot a toot manager A D if [ -f "${OUTPUTFILE}_TEMP" ]; then rm "${OUTPUTFILE}_TEMP" fi touch "${OUTPUTFILE}_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="" found_line=$(echo "$INPUT" | grep -e "^$pkg") 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" >>"${OUTPUTFILE}_TEMP" done # notify on any removed packages 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 <<<"<(echo $INPUT | tail +2)" # show file changes if [ -f "$OUTPUTFILE"_TEMP ]; then changes=$(diff --color=always -y --suppress-common-lines <(echo "$INPUT") <(sort "$OUTPUTFILE"_TEMP | tail -n+2)) printf "FILE CHANGES:\n=============\n%s" "$changes" fi # actually write changes to file if [ -z "$DRYRUN" ]; then while IFS= read -r line; do sed -i -e "/^${line//\//\\/}$/d" "$OUTPUTFILE"_TEMP done <<< "$INPUT" cat <(printf "Name\tDescription\tSource\tTarget\n") "${OUTPUTFILE}_TEMP" > "$OUTPUTFILE" fi rm "${OUTPUTFILE}_TEMP"