blob: b07ea1befeb5d2799d685c1749131b67f1573efd (
plain) (
tree)
|
|
#!/bin/sh -e
# checkapk - find ABI breakages in package upgrades
# Copyright (c) 2012 Natanael Copa <natanael.copa@gmail.com>
#
# Distributed under GPL-2
#
program_version=@VERSION@
datadir=@datadir@
if ! [ -f "$datadir/functions.sh" ]; then
echo "$datadir/functions.sh: not found" >&2
exit 1
fi
. "$datadir/functions.sh"
usage() {
cat >&2 <<-__EOF__
$program $program_version - find ABI breakages in package upgrades
Usage: $program
Run in the directory of a built package.
__EOF__
}
pkginfo() {
apk="$1"
tar -zxf "$apk" .PKGINFO
mv .PKGINFO .PKGINFO.orig
grep -E \
'^(depend|provides|provider|replaces|triggers|install_if)' \
.PKGINFO.orig | sort > .PKGINFO
touch -r .PKGINFO.orig .PKGINFO
rm .PKGINFO.orig
}
if [ $# -gt 0 ]; then
usage
exit 2
fi
if ! [ -f "$ABUILD_CONF" ] && ! [ -f "$ABUILD_USERCONF" ]; then
die "no abuild.conf found"
fi
if ! [ -f APKBUILD ]; then
die 'must be run in the directory of a built package'
fi
if ! [ -n "$CARCH" ]; then
die "failed to detect CARCH"
fi
. ./APKBUILD
startdir="$PWD"
tmpdir=$(mktemp -d -t checkpkg-script.XXXXXX)
trap "rm -rf '$tmpdir'" INT EXIT
cd "$tmpdir" || die "failed to create temp dir"
for i in $pkgname $subpackages; do
_pkgname=${i%%:*}
pkg=${_pkgname}-$pkgver-r$pkgrel
pkgfile=${pkg}.apk
repodir=${startdir%/*}
repo=${repodir##*/}
for filepath in "$PKGDEST"/$pkgfile "$REPODEST"/$repo/$CARCH/$pkgfile "$startdir"/$pkgfile; do
if [ -f "$filepath" ]; then
break
fi
done
[ -f "$filepath" ] || die "can't find new apk $pkgfile"
# generate a temp repositories file with only the http(s) repos
grep -E "^https?:" /etc/apk/repositories > "$tmpdir/repositories"
if ! oldapk="$(apk fetch --repositories-file "$tmpdir/repositories" "$_pkgname")"; then
warning "Could not download $_pkgname (network error or new package)"
continue
fi
[ -n "$oldapk" ] || die "cannot determine new apk name"
oldapk="${oldapk##Downloading }.apk"
[ -e "$oldapk" ] || die "can't find old apk $oldapk"
pkginfo "$oldapk"
mv .PKGINFO "pkginfo-$_pkgname-old"
pkginfo "$filepath"
mv .PKGINFO "pkginfo-$_pkgname-new"
tar -ztf "$oldapk" | grep -ve '^\.SIGN\.' | sort > "filelist-$_pkgname-old"
touch -r "pkginfo-$_pkgname-old" "filelist-$_pkgname-old"
tar -ztf "$filepath" | grep -v '^\.SIGN\.' | sort > "filelist-$_pkgname-new"
touch -r "pkginfo-$_pkgname-new" "filelist-$_pkgname-new"
diff -u "filelist-$_pkgname-old" "filelist-$_pkgname-new" || true
diff -u "pkginfo-$_pkgname-old" "pkginfo-$_pkgname-new" | tee pkginfo-diff
soname=
for soname in $(awk '/^-provides = so:/ { print $3 }' pkginfo-diff); do
sover_old="${soname#*=}"
soname="${soname%=*}"
basename="${soname%%.so*}.so"
soname_new="$(grep -F "provides = $basename" \
"pkginfo-$_pkgname-new" | cut -d ' ' -f 3)"
sover_new="${soname_new#*=}"
soname_new="${soname_new%=*}"
if [ -z "$soname_new" ]; then
warning "No new version of $soname! (or in a different apk)"
else
warning "$soname=$sover_old -> $soname_new=$sover_new"
fi
rdeps="$(apk search --repositories-file "$tmpdir/repositories" \
--rdepends --quiet "$soname" | sort -u)"
real_rdeps=
for i in $rdeps; do
self=0
for j in $pkgname $subpackages; do
[ "$i" = "$j" ] || continue
self=1
break
done
[ "$self" -eq 0 ] && real_rdeps="$real_rdeps
$i"
done
if [ -n "$real_rdeps" ]; then
warning "Dependents on $soname:"
printf '%s\n' "$real_rdeps" | sed '/^$/d; s/^/\t/' >&2
else
msg "No dependents on $soname."
fi
done
[ -n "$soname" ] || msg "No soname differences for $_pkgname."
rm "$oldapk"
done
|