xonotic/misc/tools/zipdiff
2010-03-18 14:22:15 +01:00

172 lines
2.5 KiB
Bash
Executable File

#!/bin/sh
usage()
{
cat <<EOF
Usage:
$0 -o difference.zip -f from.zip -t to.zip
$0 -f from.zip -t to.zip
EOF
exit 1
}
output=
from=
to=
excludes=
while [ $# -gt 0 ]; do
o=$1
shift
case "$o" in
-o)
output=$1
shift
;;
-f)
from=$1
shift
;;
-t)
to=$1
shift
;;
-x)
excludes="$excludes $1"
shift
;;
*)
usage
;;
esac
done
[ -n "$from" ] || usage
[ -n "$to" ] || usage
found()
{
type=$1
source=$2
echo >&2 "$type: $source"
case "$type" in
new|changed|deleted)
echo "$source"
;;
excluded)
;;
deleted|*)
echo >&2 " * Sorry, can't handle deletion of $source."
;;
esac
}
tempdir=`mktemp -d -t zipdiff.XXXXXX`
newline="
"
fromlist="$(zipinfo -1 "$from" | grep -v /\$)"
tolist="$(zipinfo -1 "$to" | grep -v /\$)"
diffit()
{
echo "$fromlist" | while IFS= read -r line; do
case "$newline$tolist$newline" in
*$newline$line$newline*)
;;
*)
isexcluded=false
for P in $excludes; do
case "$line" in
$P)
found excluded "$line"
isexcluded=true
break
;;
esac
done
if ! $isexcluded; then
found deleted "$line"
fi
;;
esac
done
echo "$tolist" | while IFS= read -r line; do
case "$newline$fromlist$newline" in
*$newline$line$newline*)
# check if equal
isexcluded=false
for P in $excludes; do
case "$line" in
$P)
found excluded "$line"
isexcluded=true
break
;;
esac
done
if ! $isexcluded; then
unzip -p "$from" "$line" > "$tempdir/v1"
unzip -p "$to" "$line" > "$tempdir/v2"
if ! diff --brief "$tempdir/v1" "$tempdir/v2" >/dev/null 2>&1; then
found changed "$line"
fi
rm "$tempdir/v1"
rm "$tempdir/v2"
fi
;;
*)
# check if equal
isexcluded=false
for P in $excludes; do
case "$line" in
$P)
found excluded "$line"
isexcluded=true
break
;;
esac
done
if ! $isexcluded; then
found new "$line"
fi
;;
esac
done
}
result=`diffit`
case "$output" in
'')
;;
*)
rm -f "$output"
echo "$result" | while IFS= read -r line; do
echo >&2 "extracting $line..."
dline=./$line
mkdir -p "$tempdir/${dline%/*}"
unzip -p "$to" "$line" > "$tempdir/$line" # this may create an empty file - don't care, DP handles this as deletion
done
case "$output" in
/*)
;;
*)
output=`pwd`/$output
;;
esac
cd "$tempdir"
#zip -9r "$output" .
7za a -tzip -mx=9 "$output" .
cd ..
;;
esac
rm -rf "$tempdir"