diff options
-rw-r--r-- | checkapk.in | 93 |
1 files changed, 73 insertions, 20 deletions
diff --git a/checkapk.in b/checkapk.in index f8a8d1b..b07ea1b 100644 --- a/checkapk.in +++ b/checkapk.in @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/sh -e # checkapk - find ABI breakages in package upgrades # Copyright (c) 2012 Natanael Copa <natanael.copa@gmail.com> @@ -15,7 +15,6 @@ if ! [ -f "$datadir/functions.sh" ]; then fi . "$datadir/functions.sh" - usage() { cat >&2 <<-__EOF__ $program $program_version - find ABI breakages in package upgrades @@ -26,6 +25,17 @@ usage() { __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 @@ -62,28 +72,71 @@ for i in $pkgname $subpackages; do break fi done - [ -f "$filepath" ] || die "can't find $pkgfile" + [ -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 + grep -E "^https?:" /etc/apk/repositories > "$tmpdir/repositories" - apk fetch --quiet --repositories-file $tmpdir/repositories --stdout $_pkgname \ - | tar -ztf - | grep -v '^\.SIGN\.' | sort > filelist-$_pkgname-old \ - || die "failed to download old pkg, maybe run 'apk update'?" + 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 - tar -ztf "$filepath" | grep -v '^\.SIGN\.' | sort > "filelist-$_pkgname" + 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 - diff -u "filelist-$_pkgname-old" "filelist-$_pkgname" + 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." - if diff "filelist-$_pkgname-old" "filelist-$_pkgname" | grep '\.so' > /dev/null 2>&1; then - mkdir -p pkg - cd pkg - tar -zxf "$filepath" > /dev/null - diff "../filelist-$_pkgname-old" "../filelist-$_pkgname" | awk '/>.*\.so/{$1 = ""; print $0}' | while read i; do - echo "${i}: " "$(objdump -p "$i" | grep SONAME)" - done - cd .. - else - msg "No soname differences for $_pkgname." - fi + rm "$oldapk" done |