[arch-projects] [devtools] [PATCH 4/4] common: implement find_cached_package

Dave Reisner dreisner at archlinux.org
Sun Oct 20 16:17:45 EDT 2013


This function (currently) searches through $PWD and $PKGDEST looking
for a tarball matching the requested package name, architecture, and
pkgver. If found, it writes the full path to the located package to
stdout and returns 0, else 1. If more than 1 match is found, it's
treated as an error and the user will need to figure out what to do.

Use this in checkpkg and commitpkg, which previously implemented their
own less complete logic, to locate the build artifacts they rely on.

Signed-off-by: Dave Reisner <dreisner at archlinux.org>
---
This fixes a regression I caused in 9c85d116f042 which didn't consider finding
the package in PKGDEST. I took the heavy handed approach and wrote a generic
function to find cached packages since we do this in both checkpkg and
commitpkg (and maybe some day elsewhere). Neither of the existing solutions
are particularly thorough.

 checkpkg.in   | 14 ++++--------
 commitpkg.in  | 24 +++------------------
 lib/common.sh | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 76 insertions(+), 31 deletions(-)

diff --git a/checkpkg.in b/checkpkg.in
index 9a32d00..3ad912f 100644
--- a/checkpkg.in
+++ b/checkpkg.in
@@ -29,18 +29,12 @@ STARTDIR=$(pwd)
 TEMPDIR=$(mktemp -d --tmpdir checkpkg-script.XXXX)
 
 for _pkgname in "${pkgname[@]}"; do
-  pkgfile=(${_pkgname}-$(get_full_version $_pkgname)-${CARCH}.pkg.tar?(.?z))
-	if (( ${#pkgfile[*]} != 1 )); then
-		die 'Ambiguous package name: %s\n' "${pkgfile[*]}"
+	target_pkgver=$(get_full_version "$_pkgname")
+	if ! pkgfile=$(find_cached_package "$_pkgname" "$target_pkgver" "$CARCH"); then
+		die 'tarball not found for package: %s' "${_pkgname}-$target_pkgver"
 	fi
 
-	if [[ -f "$STARTDIR/$pkgfile" ]]; then
-		ln -s "$STARTDIR/$pkgfile" "$TEMPDIR/$pkgfile"
-	elif [[ -f "$PKGDEST/$pkgfile" ]]; then
-		ln -s "$PKGDEST/$pkgfile" "$TEMPDIR/$pkgfile"
-	else
-		die "File \"$pkgfile\" doesn't exist"
-	fi
+	ln -s "$pkgfile" "$TEMPDIR"
 
 	pkgurl=$(pacman -Spdd --print-format '%l' --noconfirm "$_pkgname")
 
diff --git a/commitpkg.in b/commitpkg.in
index d584f92..809ff81 100644
--- a/commitpkg.in
+++ b/commitpkg.in
@@ -2,22 +2,6 @@
 
 m4_include(lib/common.sh)
 
-getpkgfile() {
-	case $# in
-		0)
-			error 'No canonical package found!'
-			return 1
-			;;
-		[!1])
-			error 'Failed to canonicalize package name -- multiple packages found:'
-			msg2 '%s' "$@"
-			return 1
-			;;
-	esac
-
-	echo "$1"
-}
-
 # Source makepkg.conf; fail if it is not found
 if [[ -r '/etc/makepkg.conf' ]]; then
 	source '/etc/makepkg.conf'
@@ -99,9 +83,8 @@ for _arch in ${arch[@]}; do
 	for _pkgname in ${pkgname[@]}; do
 		fullver=$(get_full_version $_pkgname)
 
-		if pkgfile=$(shopt -s nullglob;
-				getpkgfile "${PKGDEST+$PKGDEST/}$_pkgname-$fullver-${_arch}".pkg.tar.?z); then
-			if grep -q "packager = Unknown Packager" <(bsdtar -xOqf $pkgfile .PKGINFO); then
+		if pkgfile=$(find_cached_package "$_pkgname" "$_arch" "$fullver"); then
+			if grep -q "packager = Unknown Packager" <(bsdtar -xOqf "$pkgfile" .PKGINFO); then
 				die "PACKAGER was not set when building package"
 			fi
 		fi
@@ -151,8 +134,7 @@ for _arch in ${arch[@]}; do
 	for _pkgname in ${pkgname[@]}; do
 		fullver=$(get_full_version $_pkgname)
 
-		if ! pkgfile=$(shopt -s nullglob;
-				getpkgfile "${PKGDEST+$PKGDEST/}$_pkgname-$fullver-${_arch}".pkg.tar.?z); then
+		if ! pkgfile=$(find_cached_package "$_pkgname" "$fullver" "${_arch}"); then
 			warning "Skipping $_pkgname-$fullver-$_arch: failed to locate package file"
 			skip_arches+=($_arch)
 			continue 2
diff --git a/lib/common.sh b/lib/common.sh
index 3ec26ff..1812cb7 100644
--- a/lib/common.sh
+++ b/lib/common.sh
@@ -1,6 +1,8 @@
 # Avoid any encoding problems
 export LANG=C
 
+shopt -s extglob
+
 # check if messages are to be printed using color
 unset ALL_OFF BOLD BLUE GREEN RED YELLOW
 if [[ -t 2 ]]; then
@@ -154,3 +156,70 @@ slock() {
 		stat_done
 	fi
 }
+
+##
+# usage: pkgver_equal( $pkgver1, $pkgver2 )
+##
+pkgver_equal() {
+	local left right
+
+	if [[ $1 = *-* && $2 = *-* ]]; then
+		# if both versions have a pkgrel, then they must be an exact match
+		[[ $1 = "$2" ]]
+	else
+		# otherwise, trim any pkgrel and compare the bare version.
+		[[ ${1%%-*} = "${2%%-*}" ]]
+	fi
+}
+
+##
+#  usage: find_cached_package( $pkgname, $pkgver, $arch )
+#
+#    $pkgver can be supplied with or without a pkgrel appended.
+#    If not supplied, any pkgrel will be matched.
+##
+find_cached_package() {
+	local searchdirs=("$PWD" "$PKGDEST") results=()
+	local targetname=$1 targetver=$2 targetarch=$3
+	local dir pkg pkgbasename pkgparts name ver rel arch size results
+
+	for dir in "${searchdirs[@]}"; do
+		[[ -d $dir ]] || continue
+
+		for pkg in "$dir"/*.pkg.tar?(.?z); do
+			[[ -f $pkg ]] || continue
+
+			# split apart package filename into parts
+			pkgbasename=${pkg##*/}
+			pkgbasename=${pkgbasename%.pkg.tar?(.?z)}
+
+			arch=${pkgbasename##*-}
+			pkgbasename=${pkgbasename%-"$arch"}
+
+			rel=${pkgbasename##*-}
+			pkgbasename=${pkgbasename%-"$rel"}
+
+			ver=${pkgbasename##*-}
+			name=${pkgbasename%-"$ver"}
+
+			if [[ $targetname = "$name" && $targetarch = "$arch" ]] &&
+					pkgver_equal "$targetver" "$ver-$rel"; then
+				results+=("$pkg")
+			fi
+		done
+	done
+
+	case ${#results[*]} in
+		0)
+			return 1
+			;;
+		1)
+			printf '%s\n' "$results"
+			return 0
+			;;
+		*)
+			error 'Multiple packages found:'
+			printf '\t%s\n' "${results[@]}"
+			return 1
+	esac
+}
-- 
1.8.4.1



More information about the arch-projects mailing list