rpm-build/scripts/find-package.in

225 lines
6.8 KiB
Plaintext
Raw Normal View History

#!/bin/sh -efu
2002-03-25 23:37:46 +03:00
#
2003-04-22 19:11:52 +04:00
# Copyright (C) 2002-2003 Dmitry V. Levin <ldv@altlinux.org>
# Copyright (C) 2007 Alexey Tourbin <at@altlinux.org>
2002-03-25 23:37:46 +03:00
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
2003-11-09 19:47:45 +03:00
. @RPMCONFIGDIR@/functions
2002-03-25 23:37:46 +03:00
RPM_FINDPACKAGE_PATH="${RPM_FINDPACKAGE_PATH-}:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin"
RPM_FINDPACKAGE_PATH="$(IFS="$IFS:"; set -f; echo '' $RPM_FINDPACKAGE_PATH |sed -e 's/ */:/g; s/^://')"
Debug "RPM_FINDPACKAGE_PATH=$RPM_FINDPACKAGE_PATH"
# Below we use 'local Verbose=Info' to increase per-case verbosity.
Verbose=Verbose
FindByPath()
2002-03-25 23:37:46 +03:00
{
# Dependence name starts with `/'.
local f="$1" rep="$2" package; shift 2 || return
2002-03-25 23:37:46 +03:00
# Does it start with buildroot?
if [ -n "${RPM_BUILD_ROOT-}" ] && [ -z "${rep##$RPM_BUILD_ROOT*}" ]; then
Info "$f: invalid dependence: $rep"
return 1
fi
2003-04-22 19:11:52 +04:00
# Does it belong to buildroot?
if [ -n "${RPM_BUILD_ROOT-}" ] && [ -e "$RPM_BUILD_ROOT$rep" ]; then
$Verbose "$f: $rep -> \$RPM_BUILD_ROOT$rep (skip)"
return
fi
2003-04-22 19:11:52 +04:00
# Is it an alternative?
if readlink "$rep" |grep -qs '^/etc/alternatives/'; then
$Verbose "$f: $rep -> $rep (alternative)"
printf %s\\n "$rep"
return
fi
2003-04-22 19:11:52 +04:00
# Always try package binary index.
local idx_bin="${RPM_PKG_CONTENTS_INDEX_BIN-}" try_idx_bin=1
[ -n "$idx_bin" ] && [ -s "$idx_bin" ] && [ -r "$idx_bin" ] || try_idx_bin=
if [ -n "$try_idx_bin" ]; then
package="$(awk -v "f=$rep" '($1 == f) {print $2}' "$idx_bin" |sort -u)"
local n="$(IFS=$'\n'; set -- $package; echo $#)"
if [ "$n" = 1 ]; then
$Verbose "$f: $rep -> $package (via contents_index_bin)"
printf %s\\n "$package"
return
elif [ "$n" -gt 1 ]; then
Info "$f: $rep indexed by:$(echo '' $package)"
Info "$f: $rep -> $rep (raw, ambiguous, via contents_index_bin)"
printf %s\\n "$rep"
return
fi
fi
# Maybe try pkg complete index.
local idx_all="${RPM_PKG_CONTENTS_INDEX_ALL-}" try_idx_all=1
[ -n "$idx_all" ] && [ -s "$idx_all" ] && [ -r "$idx_all" ] || try_idx_all=
case "$try_idx_bin$rep" in
1/bin/* | 1/sbin/* | 1/usr/bin/* | 1/usr/sbin/* )
# Binary index already checked for standard *bin/* entries.
# No need to check complete index.
try_idx_all=
esac
if [ -n "$try_idx_all" ]; then
# Checking complete index is expensive.
local Verbose=Info
Info "$f: checking contents_index_all for $rep"
# Complete package index is possibly gzipped.
package="$(gzip -cdfq "$idx_all" |awk -v "f=$rep" '($1 == f) {print $2}' |sort -u)"
local n="$(IFS=$'\n'; set -- $package; echo $#)"
if [ "$n" = 1 ]; then
Info "$f: $rep -> $package (via contents_index_all)"
printf %s\\n "$package"
return
elif [ "$n" -gt 1 ]; then
Info "$f: $rep indexed by:$(echo '' $package)"
Info "$f: $rep -> $rep (raw, ambiguous, via contents_index_all)"
printf %s\\n "$rep"
return
fi
fi
2003-04-22 19:11:52 +04:00
# Check package database.
if package="$(rpmquery --whatprovides --queryformat='%{NAME}\n' -- "$rep")"; then
package="$(printf %s "$package" |LC_COLLATE=C sort -u)"
local n="$(IFS=$'\n'; set -- $package; echo $#)"
if [ "$n" = 1 ]; then
$Verbose "$f: $rep -> $package (via rpmdb)"
printf %s\\n "$package"
return
elif [ "$n" -gt 1 ]; then
Info "$f: $rep provided by:$(echo '' $package)"
Info "$f: $rep -> $rep (raw, ambiguous, via rpmdb)"
printf %s\\n "$rep"
return
fi
fi
2003-04-22 19:11:52 +04:00
# Not found; output raw dependence.
Info "$f: $rep -> $rep (raw, not found)"
printf %s\\n "$rep"
}
2003-04-22 19:11:52 +04:00
FindByName()
{
local f="$1" r="$2" rep package; shift 2 || return
2003-04-22 19:11:52 +04:00
# Check buildroot first.
if [ -n "${RPM_BUILD_ROOT-}" ]; then
local RPATH
RPATH="$(printf %s "$RPM_FINDPACKAGE_PATH" |sed -e "s|[^:]\+|$RPM_BUILD_ROOT&|g")"
if rep="$(PATH="$RPATH" /usr/bin/which -- "$r" 2>/dev/null)"; then
$Verbose "$f: $r -> \$RPM_BUILD_ROOT${rep#$RPM_BUILD_ROOT} (skip)"
return
fi
fi
2003-04-22 19:11:52 +04:00
# Check for pkg contents binary index.
rep= package=
if [ -n "${RPM_PKG_CONTENTS_INDEX_BIN-}" ] && [ -s "$RPM_PKG_CONTENTS_INDEX_BIN" ] && [ -r "$RPM_PKG_CONTENTS_INDEX_BIN" ]; then
local out="$(awk -v r="$r" -v RPM_FINDPACKAGE_PATH="$RPM_FINDPACKAGE_PATH" '
BEGIN {
n = split(RPM_FINDPACKAGE_PATH, ary, ":")
for (i = 1; i <= n; i++) {
dir = ary[i]
sub("/+$", "", dir)
find-package (FindByName): optimized awk script It looks like that, unlike in perl, pattern matching in awk is very slow. Perhaps they just don't have regexp engine hackers like Larry Wall or Ilya Zakharevich (or, most recently, Yves Orton aka demerphq). That's okay, since I can rewrite the script without pattern matching at all. That is, I don't have to split each index line into dir+basename, because I can prepare all valid absolute pathnames in advance. Old speed: $ time /usr/lib/rpm/shell.req -v /dev/stdin <<<`rpm -ql rpm-utils |sed -n 's|/usr/bin/||p'` shell.req: add_changelog -> /usr/bin/add_changelog -> rpm-utils (via content index) shell.req: buildreq -> /usr/bin/buildreq -> rpm-utils (via content index) shell.req: cleanup_spec -> /usr/bin/cleanup_spec -> rpm-utils (via content index) shell.req: compare_packages -> /usr/bin/compare_packages -> rpm-utils (via content index) shell.req: filereq -> /usr/bin/filereq -> rpm-utils (via content index) shell.req: packageof -> /usr/bin/packageof -> rpm-utils (via content index) shell.req: packagereq -> /usr/bin/packagereq -> rpm-utils (via content index) shell.req: rebuild_package -> /usr/bin/rebuild_package -> rpm-utils (via content index) shell.req: rebuild_packages -> /usr/bin/rebuild_packages -> rpm-utils (via content index) shell.req: rpmdups -> /usr/bin/rpmdups -> rpm-utils (via content index) shell.req: rpmevrcmp -> /usr/bin/rpmevrcmp -> rpm-utils (via content index) shell.req: rpmrdups -> /usr/bin/rpmrdups -> rpm-utils (via content index) shell.req: rpmvercmp -> /usr/bin/rpmvercmp -> rpm-utils (via content index) shell.req: stamp_spec -> /usr/bin/stamp_spec -> rpm-utils (via content index) rpm-utils /usr/lib/rpm/shell.req -v /dev/stdin <<< 5.37s user 0.11s system 96% cpu 5.683 total $ New speed: $ time /usr/lib/rpm/shell.req -v /dev/stdin <<<`rpm -ql rpm-utils |sed -n 's|/usr/bin/||p'` shell.req: add_changelog -> /usr/bin/add_changelog -> rpm-utils (via content index) shell.req: buildreq -> /usr/bin/buildreq -> rpm-utils (via content index) shell.req: cleanup_spec -> /usr/bin/cleanup_spec -> rpm-utils (via content index) shell.req: compare_packages -> /usr/bin/compare_packages -> rpm-utils (via content index) shell.req: filereq -> /usr/bin/filereq -> rpm-utils (via content index) shell.req: packageof -> /usr/bin/packageof -> rpm-utils (via content index) shell.req: packagereq -> /usr/bin/packagereq -> rpm-utils (via content index) shell.req: rebuild_package -> /usr/bin/rebuild_package -> rpm-utils (via content index) shell.req: rebuild_packages -> /usr/bin/rebuild_packages -> rpm-utils (via content index) shell.req: rpmdups -> /usr/bin/rpmdups -> rpm-utils (via content index) shell.req: rpmevrcmp -> /usr/bin/rpmevrcmp -> rpm-utils (via content index) shell.req: rpmrdups -> /usr/bin/rpmrdups -> rpm-utils (via content index) shell.req: rpmvercmp -> /usr/bin/rpmvercmp -> rpm-utils (via content index) shell.req: stamp_spec -> /usr/bin/stamp_spec -> rpm-utils (via content index) rpm-utils /usr/lib/rpm/shell.req -v /dev/stdin <<< 0.34s user 0.10s system 88% cpu 0.499 total $ More than ten times faster, wow! I didn't know regexp engine could be that slow, really.
2007-03-11 23:40:37 +03:00
file = dir "/" r
if (dir && !(file in FILES))
FILES[file] = i
}
}
find-package (FindByName): optimized awk script It looks like that, unlike in perl, pattern matching in awk is very slow. Perhaps they just don't have regexp engine hackers like Larry Wall or Ilya Zakharevich (or, most recently, Yves Orton aka demerphq). That's okay, since I can rewrite the script without pattern matching at all. That is, I don't have to split each index line into dir+basename, because I can prepare all valid absolute pathnames in advance. Old speed: $ time /usr/lib/rpm/shell.req -v /dev/stdin <<<`rpm -ql rpm-utils |sed -n 's|/usr/bin/||p'` shell.req: add_changelog -> /usr/bin/add_changelog -> rpm-utils (via content index) shell.req: buildreq -> /usr/bin/buildreq -> rpm-utils (via content index) shell.req: cleanup_spec -> /usr/bin/cleanup_spec -> rpm-utils (via content index) shell.req: compare_packages -> /usr/bin/compare_packages -> rpm-utils (via content index) shell.req: filereq -> /usr/bin/filereq -> rpm-utils (via content index) shell.req: packageof -> /usr/bin/packageof -> rpm-utils (via content index) shell.req: packagereq -> /usr/bin/packagereq -> rpm-utils (via content index) shell.req: rebuild_package -> /usr/bin/rebuild_package -> rpm-utils (via content index) shell.req: rebuild_packages -> /usr/bin/rebuild_packages -> rpm-utils (via content index) shell.req: rpmdups -> /usr/bin/rpmdups -> rpm-utils (via content index) shell.req: rpmevrcmp -> /usr/bin/rpmevrcmp -> rpm-utils (via content index) shell.req: rpmrdups -> /usr/bin/rpmrdups -> rpm-utils (via content index) shell.req: rpmvercmp -> /usr/bin/rpmvercmp -> rpm-utils (via content index) shell.req: stamp_spec -> /usr/bin/stamp_spec -> rpm-utils (via content index) rpm-utils /usr/lib/rpm/shell.req -v /dev/stdin <<< 5.37s user 0.11s system 96% cpu 5.683 total $ New speed: $ time /usr/lib/rpm/shell.req -v /dev/stdin <<<`rpm -ql rpm-utils |sed -n 's|/usr/bin/||p'` shell.req: add_changelog -> /usr/bin/add_changelog -> rpm-utils (via content index) shell.req: buildreq -> /usr/bin/buildreq -> rpm-utils (via content index) shell.req: cleanup_spec -> /usr/bin/cleanup_spec -> rpm-utils (via content index) shell.req: compare_packages -> /usr/bin/compare_packages -> rpm-utils (via content index) shell.req: filereq -> /usr/bin/filereq -> rpm-utils (via content index) shell.req: packageof -> /usr/bin/packageof -> rpm-utils (via content index) shell.req: packagereq -> /usr/bin/packagereq -> rpm-utils (via content index) shell.req: rebuild_package -> /usr/bin/rebuild_package -> rpm-utils (via content index) shell.req: rebuild_packages -> /usr/bin/rebuild_packages -> rpm-utils (via content index) shell.req: rpmdups -> /usr/bin/rpmdups -> rpm-utils (via content index) shell.req: rpmevrcmp -> /usr/bin/rpmevrcmp -> rpm-utils (via content index) shell.req: rpmrdups -> /usr/bin/rpmrdups -> rpm-utils (via content index) shell.req: rpmvercmp -> /usr/bin/rpmvercmp -> rpm-utils (via content index) shell.req: stamp_spec -> /usr/bin/stamp_spec -> rpm-utils (via content index) rpm-utils /usr/lib/rpm/shell.req -v /dev/stdin <<< 0.34s user 0.10s system 88% cpu 0.499 total $ More than ten times faster, wow! I didn't know regexp engine could be that slow, really.
2007-03-11 23:40:37 +03:00
NF==2 && ($1 in FILES) {
print FILES[$1] "\t" $1 "\t" $2
}
' "$RPM_PKG_CONTENTS_INDEX_BIN" |
sort -n |sort -u -k3 |sort -n |cut -f2-)"
local n="$(IFS=$'\n'; set -- $out; echo $#)"
if [ "$n" = 1 ]; then
rep="$(IFS=$'\t\n'; set -- $out; printf %s "$1")"
package="$(IFS=$'\t\n'; set -- $out; printf %s "$2")"
$Verbose "$r -> $rep -> $package (via contents_index_bin)"
printf %s\\n "$package"
return
elif [ "$n" -gt 1 ]; then
local Verbose=Info
Info "$f: $r indexed by:$(printf %s "$out" |sed -e 's/\t/ -> /; s/$/,/; $s/,$//' |xargs echo '')"
rep="$(IFS=$'\t\n'; set -- $out; printf %s "$1")"
package="$(IFS=$'\t\n'; set -- $out; printf %s "$2")"
local rep2="$(IFS=$'\t\n'; set -- $out; printf %s "$3")"
if [ "$rep" = "$rep2" ]; then
Info "$f: $r -> $rep -> $rep (raw, ambiguous, via contents_index_bin)"
printf %s\\n "$rep"
return
2002-03-25 23:37:46 +03:00
fi
fi
fi
# Lookup in the host system.
local irep="$rep"
if rep="$(PATH="$RPM_FINDPACKAGE_PATH" /usr/bin/which --all -- "$r" 2>/dev/null)"; then
local n="$(IFS=$'\n'; set -- $rep; echo $#)"
if [ "$n" -gt 1 ]; then
n="$(IFS=$'\n'; for f in $rep; do readlink -vm "$f"; done |sort -u |wc -l)"
if [ "$n" -gt 1 ]; then
local Verbose=Info
Info "$f: which $r:$(echo '' $rep)"
fi
rep="$(IFS=$'\n'; set -- $rep; printf %s "$1")"
fi
if [ -n "$rep" ]; then
$Verbose "$f: $r -> $rep -> ... (via which)"
FindByPath "$f" "$rep"
return
fi
fi
# Reconsult pkg contents binary index.
if [ -n "$irep" ] && [ -n "$package" ]; then
rep="$irep"
$Verbose "$f: $r -> $rep -> $package (via contents_index_bin)"
printf %s\\n "$package"
return
fi
# Not found.
Info "$f: $r not found (skip)"
}
FindPackage()
{
local f="$1" r; shift || return
for r; do
local Verbose=Verbose
case "$r" in
/*)
FindByPath "$f" "$r" ;;
*/*)
Info "$f: invalid pathname $r" ;;
-*)
Info "$f: invalid command $r" ;;
'')
;;
*)
FindByName "$f" "$r" ;;
esac
2002-03-25 23:37:46 +03:00
done
}