mirror of
https://gitlab.alpinelinux.org/alpine/abuild.git
synced 2025-03-01 09:50:31 +00:00
I rebuilt networkmanager locally and was greeted with this: >>> Size difference for networkmanager: 16 MiB -> 2772 KiB It turns out networkmanager-elogind provides networkmanager so apk info will list both, and the former is much bigger so it looked like the rebuilt package was much smaller when there was almost no difference (as expected) Fix by matching on exact package name for both lines; this is already what we were doing with the local package anyway and the apk fetch correctly picks the correct package in this case
158 lines
4.5 KiB
Bash
158 lines
4.5 KiB
Bash
#!/bin/sh
|
|
|
|
# checkapk - find ABI breakages in package upgrades
|
|
# Copyright (c) 2012 Natanael Copa <natanael.copa@gmail.com>
|
|
#
|
|
# Distributed under GPL-2.0-only
|
|
#
|
|
|
|
program_version=@VERSION@
|
|
sharedir=${ABUILD_SHAREDIR:-@sharedir@}
|
|
|
|
if ! [ -f "$sharedir/functions.sh" ]; then
|
|
echo "$sharedir/functions.sh: not found" >&2
|
|
exit 1
|
|
fi
|
|
. "$sharedir/functions.sh"
|
|
|
|
|
|
usage() {
|
|
cat <<-__EOF__
|
|
$program $program_version - find ABI breakages in package upgrades
|
|
Usage: $program [-h|--help]
|
|
|
|
Run in the directory of a built package.
|
|
|
|
Options:
|
|
-h, --help Print this help
|
|
|
|
__EOF__
|
|
}
|
|
|
|
args=$(getopt -o h --long help \
|
|
-n "$program" -- "$@")
|
|
|
|
if [ $? -ne 0 ]; then
|
|
usage >&2
|
|
exit 2
|
|
fi
|
|
eval set -- "$args"
|
|
while true; do
|
|
case $1 in
|
|
-h|--help) usage; exit 0;;
|
|
--) shift; break;;
|
|
*) exit 1;; # getopt error
|
|
esac
|
|
shift
|
|
done
|
|
|
|
if [ $# -gt 0 ]; then
|
|
usage >&2
|
|
exit 2
|
|
fi
|
|
|
|
if ! [ -f "$ABUILD_CONF" ] && ! [ -f "$ABUILD_USERCONF" ] && ! [ -f "$ABUILD_DEFCONF" ]; 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'; exit" INT EXIT
|
|
cd "$tmpdir" || die "failed to create temp dir"
|
|
|
|
# storage for downloaded/copied apks
|
|
mkdir -p apks
|
|
|
|
# default to pigz for unpacking
|
|
gunzip="$(command -v pigz || echo gzip) -d"
|
|
|
|
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 $pkgfile"
|
|
|
|
# generate a temp repositories file with only the http(s) repos
|
|
grep -E "^https?:" /etc/apk/repositories > "$tmpdir"/repositories
|
|
|
|
oldpkg=$(apk fetch --repositories-file "$tmpdir"/repositories --simulate $_pkgname 2>&1 | sed 's/^Downloading //')
|
|
if [ "${oldpkg}" = "${pkg}" ]; then
|
|
die "the built package ($_pkgname) is already in the repo"
|
|
fi
|
|
|
|
# apk info could return multiple lines if multiple packages share a provide
|
|
# (e.g. dnsmasq); filter with the exact package name and take the second line:
|
|
# 7zip-23.01-r0 installed size:
|
|
# 1668 KiB
|
|
newsize="$(apk info --repositories-file /dev/null --repository "$REPODEST"/$repo --size $_pkgname | \
|
|
grep -F "$pkg" -A1 | \
|
|
tail -n1)"
|
|
oldsize="$(apk info --repositories-file "$tmpdir"/repositories --size "$_pkgname" | \
|
|
grep -F "$oldpkg" -A1 | \
|
|
tail -n1)"
|
|
|
|
if [ "$oldsize" = "$newsize" ]; then
|
|
msg "No size differences for $_pkgname."
|
|
else
|
|
msg "Size difference for $_pkgname: $oldsize -> $newsize"
|
|
fi
|
|
|
|
apk fetch --quiet --repositories-file "$tmpdir"/repositories --stdout "$_pkgname" > apks/old.apk \
|
|
|| msg2 "Old apk for $_pkgname missing. (new package/arch? broken internet?)"
|
|
|
|
# pre-uncompress to not decompress twice
|
|
# we do a decompression + tar -t for the file list, but then later we might do a full extraction for sodiff.
|
|
# to not decompress here and then later again, store the intermediate tar
|
|
$gunzip -c 2>/dev/null < apks/old.apk > apks/old.tar &
|
|
$gunzip -c "$filepath" < "$filepath" > apks/new.tar &
|
|
wait
|
|
tar -t -f apks/old.tar 2>/dev/null | grep -v '^\.SIGN\.' | sort > "filelist-$_pkgname-old" &
|
|
tar -t -f apks/new.tar | grep -v '^\.SIGN\.' | sort > "filelist-$_pkgname-new" &
|
|
wait
|
|
|
|
diff -U3 "filelist-$_pkgname-old" "filelist-$_pkgname-new"
|
|
|
|
if diff -U0 "filelist-$_pkgname-old" "filelist-$_pkgname-new" | grep -q '\.so'; then
|
|
echo "SODIFF:"
|
|
|
|
mkdir -p "$_pkgname-pkg-old" "$_pkgname-pkg-new"
|
|
tar -C "$_pkgname-pkg-old" 2>/dev/null -x -f apks/old.tar > /dev/null &
|
|
tar -C "$_pkgname-pkg-new" -x -f apks/new.tar > /dev/null &
|
|
wait
|
|
|
|
# filter to things that start with -+ but strip the header (---/+++)
|
|
diff -U0 "filelist-$_pkgname-old" "filelist-$_pkgname-new" | grep -E '^(\+|-)[A-Za-z0-9]+' | grep '\.so' | while read -r diff_sofile; do
|
|
case "$diff_sofile" in
|
|
-*) path="$_pkgname-pkg-old"; sofile="${diff_sofile#\-}" ;;
|
|
+*) path="$_pkgname-pkg-new"; sofile="${diff_sofile#\+}" ;;
|
|
esac
|
|
|
|
# skip symlinks (only adds duplicate output or is dangling), and things that aren't valid elfs
|
|
# matching .so above matches anything with .so in the name, e.g. xyz.sourceforge
|
|
if ! [ -L "$path"/"$sofile" ] && readelf -h "$path"/"$sofile" >/dev/null 2>&1; then
|
|
echo "$diff_sofile: " "$(objdump -p "$path"/"$sofile" | grep SONAME)"
|
|
fi
|
|
done
|
|
else
|
|
msg "No soname differences for $_pkgname."
|
|
fi
|
|
done
|