#!/usr/bin/bash # pacdiff : a simple pacnew/pacsave updater # # Copyright (c) 2007 Aaron Griffin # Copyright (c) 2013-2016 Pacman Development Team # # 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 . # shopt -s extglob declare -r myname='pacdiff' declare -r myver='1.0.0' diffprog=${DIFFPROG:-'vim -d'} diffsearchpath=${DIFFSEARCHPATH:-/etc} USE_COLOR='y' declare -a oldsaves declare -i USE_FIND=0 USE_LOCATE=0 USE_PACDB=0 OUTPUTONLY=0 plain() { (( QUIET )) && return local mesg=$1; shift printf "${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&1 } msg() { (( QUIET )) && return local mesg=$1; shift printf "${GREEN}==>${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&1 } msg2() { (( QUIET )) && return local mesg=$1; shift printf "${BLUE} ->${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&1 } ask() { local mesg=$1; shift printf "${BLUE}::${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}" "$@" >&1 } warning() { local mesg=$1; shift printf "${YELLOW}==> $(gettext "WARNING:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 } error() { local mesg=$1; shift printf "${RED}==> $(gettext "ERROR:")${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2 } usage() { cat <' echo 'Copyright (C) 2013-2016 Pacman Development Team ' } 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 # check if messages are to be printed using color unset ALL_OFF BOLD BLUE GREEN RED YELLOW if [[ -t 2 && ! $USE_COLOR = "n" ]]; then # prefer terminal safe colored and bold text when tput is supported if tput setaf 0 &>/dev/null; then ALL_OFF="$(tput sgr0)" BOLD="$(tput bold)" BLUE="${BOLD}$(tput setaf 4)" GREEN="${BOLD}$(tput setaf 2)" RED="${BOLD}$(tput setaf 1)" YELLOW="${BOLD}$(tput setaf 3)" else ALL_OFF="\e[1;0m" BOLD="\e[1;1m" BLUE="${BOLD}\e[1;34m" GREEN="${BOLD}\e[1;32m" RED="${BOLD}\e[1;31m" YELLOW="${BOLD}\e[1;33m" fi fi readonly ALL_OFF BOLD BLUE GREEN RED YELLOW if ! type -p ${diffprog%% *} >/dev/null && (( ! OUTPUTONLY )); 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 ! DBPath="$(pacman-conf DBPath)"; then error "unable to read /etc/pacman.conf" usage; exit 1 fi pac_db="${DBPath:-/var/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 noet: