#!/bin/bash # pacdiff : a simple pacnew/pacorig/pacsave updater # # Copyright (c) 2007 Aaron Griffin <aaronmgriffin@gmail.com> # Copyright (c) 2013-2014 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 # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # 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} USE_COLOR='y' declare -a oldsaves declare -i USE_FIND=0 USE_LOCATE=0 USE_PACDB=0 OUTPUTONLY=0 m4_include(../scripts/library/output_format.sh) usage() { cat <<EOF ${myname} (pacman) v${myver} A simple program to merge or remove pacnew/pacorig/pacsave files. 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 database General Options: -o/--output print files instead of merging them --nocolor remove colors from output Environment 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 Example: $myname --output --locate EOF } version() { printf "%s %s\n" "$myname" "$myver" echo 'Copyright (C) 2007 Aaron Griffin <aaronmgriffin@gmail.com>' echo 'Copyright (C) 2013-2014 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 (( 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 } while [[ -n "$1" ]]; do case "$1" in -l|--locate) USE_LOCATE=1;; -f|--find) USE_FIND=1;; -p|--pacmandb) USE_PACDB=1;; -o|--output) OUTPUTONLY=1;; --nocolor) USE_COLOR='n';; -V|--version) version; exit 0;; -h|--help) usage; exit 0;; *) usage; exit 1;; esac shift done m4_include(../scripts/library/term_colors.sh) if ! type -p $diffprog >/dev/null; then error "Cannot find the $diffprog binary required for viewing differences." exit 1 fi 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 database %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*}" file_type="pac${pacfile##*.pac}" if (( OUTPUTONLY )); then echo "$pacfile" continue fi # 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 warning "$file does not exist" rm -iv "$pacfile" continue fi if cmp -s "$pacfile" "$file"; then msg2 "Files are identical, removing..." rm -v "$pacfile" else 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 q|Q) exit 0;; r|R) rm -v "$pacfile"; break ;; o|O) mv -v "$pacfile" "$file"; break ;; v|V) $diffprog "$pacfile" "$file" ask "(V)iew, (S)kip, (R)emove %s, (O)verwrite with %s, (Q)uit: [v/s/r/o/q] " "$file_type" "$file_type"; continue ;; s|S) break ;; *) 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: