# pacdiff : a simple pacnew/pacorig/pacsave updater
#
# Copyright (c) 2007 Aaron Griffin <aaronmgriffin@gmail.com>
+# Copyright (c) 2013 Pacman Development Team <pacman-dev@archlinux.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
+shopt -s extglob
+
declare -r myname='pacdiff'
declare -r myver='@PACKAGE_VERSION@'
diffprog=${DIFFPROG:-vimdiff}
diffsearchpath=${DIFFSEARCHPATH:-/etc}
-locate=0
+USE_COLOR='y'
+declare -a oldsaves
+declare -i USE_FIND=0 USE_LOCATE=0 USE_PACDB=0
+
+m4_include(../scripts/library/output_format.sh)
usage() {
- echo "$myname : a simple pacnew/pacorig/pacsave updater"
- echo "Usage : $myname [-l]"
- echo " -l/--locate makes $myname use locate rather than find"
- echo " DIFFPROG variable allows to override the default vimdiff"
- echo " DIFFSEARCHPATH allows to override the default /etc path"
- echo "Example : DIFFPROG=meld DIFFSEARCHPATH=\"/boot /etc /usr\" $myname"
+ cat <<EOF
+$myname is a simple pacnew/pacorig/pacsave updater.
+
+Usage: $myname [-l | -f | -p] [--nocolor]
+
+Search Options: select one, default: pacmandb
+ -l/--locate scan using locate
+ -f/--find scan using find
+ -p/--pacmandb scan active config files from pacman db
+
+General Options:
+ --nocolor remove colors from output
+
+Enviroment Variables:
+ DIFFPROG override the merge program: (default: vimdiff)
+ DIFFSEARCHPATH override the search path. (only when using find)
+ (default: /etc)
+
+Example: DIFFPROG=meld DIFFSEARCHPATH="/boot /etc /usr" $myname
+
+EOF
}
version() {
printf "%s %s\n" "$myname" "$myver"
echo 'Copyright (C) 2007 Aaron Griffin <aaronmgriffin@gmail.com>'
+ echo 'Copyright (C) 2013 Pacman Development Team <pacman-dev@archlinux.org>'
+}
+
+print_existing() {
+ [[ -f "$1" ]] && printf '%s\0' "$1"
}
+print_existing_pacsave(){
+ for f in "${1}"?(.+([0-9])); do
+ [[ -f $f ]] && printf '%s\0' "$f"
+ done
+}
+
cmd() {
- if [ $locate -eq 1 ]; then
- locate -0 -e -b \*.pacnew \*.pacorig \*.pacsave
- else
- find $diffsearchpath \( -name \*.pacnew -o -name \*.pacorig -o -name \*.pacsave \) -print0
+ if (( USE_LOCATE )); then
+ locate -0 -e -b \*.pacnew \*.pacorig \*.pacsave '*.pacsave.[0-9]*'
+ elif (( USE_FIND )); then
+ find $diffsearchpath \( -name \*.pacnew -o -name \*.pacorig -o -name \*.pacsave -o -name '*.pacsave.[0-9]*' \) -print0
+ elif (( USE_PACDB )); then
+ awk '/^%BACKUP%$/ {
+ while (getline) {
+ if (/^$/) { nextfile }
+ print $1
+ }
+ }' "${pac_db}"/*/files | while read -r bkup; do
+ print_existing "/$bkup.pacnew"
+ print_existing "/$bkup.pacorig"
+ print_existing_pacsave "/$bkup.pacsave"
+ done
fi
}
-if [ $# -gt 0 ]; then
- case $1 in
+while [[ -n "$1" ]]; do
+ case "$1" in
-l|--locate)
- locate=1;;
+ USE_LOCATE=1;;
+ -f|--find)
+ USE_FIND=1;;
+ -p|--pacmandb)
+ USE_PACDB=1;;
+ --nocolor)
+ USE_COLOR='n';;
-V|--version)
- version; exit 0;;
+ version; exit 0;;
-h|--help)
- usage; exit 0;;
+ usage; exit 0;;
*)
- usage; exit 1;;
+ usage; exit 1;;
esac
+ shift
+done
+
+m4_include(../scripts/library/term_colors.sh)
+
+case $(( USE_FIND + USE_LOCATE + USE_PACDB )) in
+ 0) USE_PACDB=1;; # set the default search option
+ [^1]) error "Only one search option may be used at a time"
+ usage; exit 1;;
+esac
+
+if (( USE_PACDB )); then
+ if [[ ! -r @sysconfdir@/pacman.conf ]]; then
+ error "unable to read @sysconfdir@/pacman.conf"
+ usage; exit 1
+ fi
+
+ eval $(awk '/DBPath/ {print $1$2$3}' @sysconfdir@/pacman.conf)
+ pac_db="${DBPath:-@localstatedir@/lib/pacman/}local"
+ if [[ ! -d "${pac_db}" ]]; then
+ error "unable to read pacman db %s". "${pac_db}"
+ usage; exit 1
+ fi
fi
# see http://mywiki.wooledge.org/BashFAQ/020
while IFS= read -u 3 -r -d '' pacfile; do
file="${pacfile%.pac*}"
- echo "File: $file"
+ file_type="pac${pacfile##*.pac}"
+
+ # add matches for pacsave.N to oldsaves array, do not prompt
+ if [[ $file_type = pacsave.+([0-9]) ]]; then
+ oldsaves+=("$pacfile")
+ continue
+ fi
+
+ msg "%s file found for %s" "$file_type" "$file"
if [ ! -f "$file" ]; then
- echo " $file does not exist"
- rm -i "$pacfile"
+ warning "$file does not exist"
+ rm -iv "$pacfile"
continue
fi
- check="$(cmp "$pacfile" "$file")"
- if [ -z "${check}" ]; then
- echo " Files are identical, removing..."
- rm "$pacfile"
+
+ if cmp -s "$pacfile" "$file"; then
+ msg2 "Files are identical, removing..."
+ rm -v "$pacfile"
else
- echo -n " File differences found. (V)iew, (S)kip, (R)emove: [v/s/r] "
+ ask "(V)iew, (S)kip, (R)emove %s, (O)verwrite with %s, (Q)uit: [v/s/r/o/q] " "$file_type" "$file_type"
while read c; do
case $c in
- r|R) rm "$pacfile"; break ;;
+ q|Q) exit 0;;
+ r|R) rm -v "$pacfile"; break ;;
+ o|O) mv -v "$pacfile" "$file"; break ;;
v|V)
- $diffprog "$pacfile" "$file"
- rm -i "$pacfile"; break ;;
+ $diffprog "$pacfile" "$file"
+ rm -iv "$pacfile"; break ;;
s|S) break ;;
- *) echo -n " Invalid answer. Try again: [v/s/r] "; continue ;;
+ *) ask "Invalid answer. Try again: [v/s/r/o/q] "; continue ;;
esac
done
fi
done 3< <(cmd)
+(( ${#oldsaves[@]} )) && warning "Ignoring %s" "${oldsaves[@]}"
+
exit 0
# vim: set ts=2 sw=2 noet: