#!/bin/bash
# -*- coding: utf-8 -*-

# rpmdev-diff -- Diff contents of two archives
#
# Copyright (c) 2004-2007 Ville Skyttä <ville.skytta at iki.fi>
#
# 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=

trap cleanup EXIT
cleanup()
{
    set +e
    [ -z "$tmpdir" -o ! -d "$tmpdir" ] || rm -rf "$tmpdir"
}

version()
{
    cat <<EOF
rpmdev-diff version 1.1

Copyright (c) 2004-2007 Ville Skyttä <ville.skytta@iki.fi>
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 <<EOF
rpmdev-diff diffs contents of two archives.

See rpmdev-extract(1) for information about supported archive types.
EOF
    usage
    echo ""
    echo "Report bugs to <http://bugzilla.redhat.com/>."
}

usage()
{
    cat <<EOF
Usage: rpmdev-diff [OPTION]... [DIFF_OPTIONS] FROM-ARCHIVE TO-ARCHIVE

Options:
  -l, --list    Diff lists of files in archives, not files themselves.
  -h, --help    Print help message and exit.
  -v, --version Print version information and exit.
  diff-options  Options passed to diff(1), in addition to -r (default: -Nu).
                The first argument not starting with a '-' ends diff-options.
EOF
}

while true ; do
    case "$1" in
        -l|--list)    [ -n "$list" ] && diffopts="$diffopts $1" || list=true ;;
        -h|--help)    help ; exit 0 ;;
        -v|--version) version ; exit 0 ;;
        -*)           diffopts="$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

diffopts="-r ${diffopts:--Nu}"

tmpdir=`mktemp -d /tmp/rpmdev-diff.XXXXXX`

mkdir "$tmpdir/old" "$tmpdir/new"
rpmdev-extract -q -C "$tmpdir/old" "$1"
rpmdev-extract -q -C "$tmpdir/new" "$2"

# 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

# Here we go.
if [ -n "$list" ] ; then
    find "$old" | sort | cut -d/ -f 2- -s > "$old.files"
    find "$new" | sort | cut -d/ -f 2- -s > "$new.files"
    diff $diffopts "$old.files" "$new.files"
else
    diff $diffopts "$old" "$new"
fi
