summaryrefslogblamecommitdiff
path: root/checkapk.in
blob: b07ea1befeb5d2799d685c1749131b67f1573efd (plain) (tree)
1
2
3
4
5
6
7
8
9
            
 





                                                            
                         



                                                   
              

                         
 
         


                                                                                  
 
                                                        
 
               

 










                                                                            



                     
 
                                                               

                                  

                          
                                                             

  



                                    



                                             
                                
                                               

                                  
                         

                                        

                              
 
                                                                                                      



                                           
                                                               
 
                                                                       
                                                                         
 



































                                                                                               
 













                                                                                
 







                                                                              
 
                    
    
#!/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