#!/bin/bash # -*- coding: utf-8 -*- # rpmdev-diff -- Diff contents of two archives # # Copyright (c) 2004-2010 Ville Skyttä # # 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, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA set -e unset CDPATH tmpdir= diffopts= list= long= contents= meta= diffcopts=-Nup diffoopts=-U0 trap cleanup EXIT cleanup() { set +e [ -z "$tmpdir" -o ! -d "$tmpdir" ] || rm -rf "$tmpdir" } version() { cat < 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. EOF } help() { cat <." } usage() { cat </dev/null } while true ; do case $1 in -l|--list) if [[ $list$diffopts ]] ; then diffopts+=" $1" else list=true fi ;; -L|--long-list) if [[ $long$diffopts ]] ; then diffopts+=" $1" else long=true fi ;; -c|--contents) if [[ $contents$diffopts ]] ; then diffopts+=" $1" else contents=true fi ;; -m|--metadata) if [[ $meta$diffopts ]] ; then diffopts+=" $1" else meta=true fi ;; -h|--help) if [[ $diffopts ]] ; then diffopts+=" $1" else help exit 0 fi ;; -v|--version) if [[ $diffopts ]] ; then diffopts+=" $1" else version exit 0 fi ;; -*) diffopts+=" $1" ;; *) break ;; esac shift done if [[ $# -lt 2 ]] ; then usage exit 1 fi for file in "$1" "$2" ; do if [[ ! -f $file ]] ; then [[ -e $file ]] && \ echo "Error: not a regular file: '$file'" >&2 || echo "Error: file does not exist: '$file'" >&2 exit 1 fi done tmpdir=`mktemp -d ${TMPDIR:-/tmp}/rpmdev-diff.XXXXXX` mkdir "$tmpdir/old" "$tmpdir/new" rpmdev-extract -q -C "$tmpdir/old" "$1" rpmdev-extract -q -C "$tmpdir/new" "$2" if ${meta:-false} ; then set +e rpm_meta "$1" > "$tmpdir/old.meta" rpm_meta "$2" > "$tmpdir/new.meta" set -e fi # It would be nice if rpmdev-extract could do some of the chmods. find "$tmpdir"/* -type d -exec chmod u+rx {} ';' # Note: -exec, not xargs here. chmod -R u+rw "$tmpdir"/* cd "$tmpdir" # Did the archives uncompress into base dirs? if [[ $(ls -1d old/* | wc -l) -eq 1 ]] ; then old=$(ls -1d old/*) else old=old fi if [[ $(ls -1d new/* | wc -l) -eq 1 ]] ; then new=$(ls -1d new/*) else new=new fi # Fixup base dirs to the same level. if [[ $(basename "$old") != $(basename "$new") ]] ; then if [[ $old != old ]] ; then mv "$old" . old=`basename "$old"` fi if [[ $new != new ]] ; then mv "$new" . new=`basename "$new"` fi fi # Contents mode is the default. if [[ -z $list$long$meta$contents ]] ; then contents=true else contents=${contents:-false} fi list=${list:-false} long=${long:-false} meta=${meta:-false} # Here we go. if $meta ; then set +e diff ${diffopts:-$diffoopts} old.meta new.meta [[ $? -eq 0 || $? -eq 1 ]] || exit $? set -e fi if $list ; then find "$old" | sort | cut -d/ -f 2- -s > "$old.files" find "$new" | sort | cut -d/ -f 2- -s > "$new.files" set +e diff ${diffopts:-$diffoopts} "$old.files" "$new.files" [[ $? -eq 0 || $? -eq 1 ]] || exit $? set -e fi if $long ; then find "$old" -ls | \ perl -pe "s|^(?:[\d\s]*)(\S+)(?:\s+\d+)(.+)$|\1\2| ; s|.*\s\Q$old\E$|| ; s|(\s)\Q$old/\E|\1|" | \ sort > "$old.files" find "$new" -ls | \ perl -pe "s|^(?:[\d\s]*)(\S+)(?:\s+\d+)(.+)$|\1\2| ; s|.*\s\Q$new\E$|| ; s|(\s)\Q$new/\E|\1|" | \ sort > "$new.files" set +e diff ${diffopts:-$diffoopts} "$old.files" "$new.files" [[ $? -eq 0 || $? -eq 1 ]] || exit $? set -e fi if $contents ; then set +e diff -r ${diffopts:-$diffcopts} "$old" "$new" [[ $? -eq 0 || $? -eq 1 ]] || exit $? set -e fi