5909f93e30
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.
186 lines
5.6 KiB
Bash
Executable File
186 lines
5.6 KiB
Bash
Executable File
#!/bin/sh -efu
|
|
#
|
|
# Copyright (C) 2002-2003 Dmitry V. Levin <ldv@altlinux.org>
|
|
# Copyright (C) 2007 Alexey Tourbin <at@altlinux.org>
|
|
#
|
|
# 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
|
|
#
|
|
|
|
. @RPMCONFIGDIR@/functions
|
|
|
|
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"
|
|
|
|
FindByPath()
|
|
{
|
|
# Dependence name starts with `/'.
|
|
local f="$1" rep="$2" package; shift 2 || return
|
|
|
|
# Does it start with buildroot?
|
|
if [ -n "${RPM_BUILD_ROOT-}" ] && [ -z "${rep##$RPM_BUILD_ROOT*}" ]; then
|
|
Info "$f: invalid dependence: $rep"
|
|
return 1
|
|
fi
|
|
|
|
# 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
|
|
|
|
# Is it an alternative?
|
|
if readlink "$rep" |grep -qs '^/etc/alternatives/'; then
|
|
Verbose "$f: $rep -> $rep (alternative)"
|
|
printf %s\\n "$rep"
|
|
return
|
|
fi
|
|
|
|
# Check for pkg contents complete index and pkg binary index.
|
|
local idx
|
|
for idx in "${RPM_PKG_CONTENTS_INDEX_ALL-}" "${RPM_PKG_CONTENTS_INDEX_BIN-}"; do
|
|
[ -n "$idx" ] && [ -s "$idx" ] && [ -r "$idx" ] || continue
|
|
package="$(awk -v "f=$rep" '($1 == f) {print $2}' "$idx" |sort -u)"
|
|
local n="$(IFS=$'\n'; set -- $package; echo $#)"
|
|
if [ "$n" = 1 ]; then
|
|
Verbose "$f: $rep -> $package (via content index)"
|
|
printf %s\\n "$package"
|
|
return
|
|
elif [ "$n" -gt 1 ]; then
|
|
Info "$f: $rep indexed by:$(echo '' $package)"
|
|
Verbose "$f: $rep -> $rep (raw, ambiguous, via content index)"
|
|
printf %s\\n "$rep"
|
|
return
|
|
fi
|
|
done
|
|
|
|
# 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)"
|
|
Verbose "$f: $rep -> $rep (raw, ambiguous, via rpmdb)"
|
|
printf %s\\n "$rep"
|
|
return
|
|
fi
|
|
fi
|
|
|
|
# Not found; output raw dependence.
|
|
Verbose "$f: $rep -> $rep (raw, not found)"
|
|
printf %s\\n "$rep"
|
|
}
|
|
|
|
FindByName()
|
|
{
|
|
local f="$1" r="$2" rep package; shift 2 || return
|
|
|
|
# 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
|
|
|
|
# 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)
|
|
file = dir "/" r
|
|
if (dir && !(file in FILES))
|
|
FILES[file] = i
|
|
}
|
|
}
|
|
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 content index)"
|
|
printf %s\\n "$package"
|
|
return
|
|
elif [ "$n" -gt 1 ]; then
|
|
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
|
|
Verbose "$f: $r -> $rep -> $rep (raw, ambiguous, via content index)"
|
|
printf %s\\n "$rep"
|
|
return
|
|
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)"
|
|
[ "$n" = 1 ] || Info "$f: which $r:$(echo '' $rep)"
|
|
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 content index)"
|
|
printf %s\\n "$package"
|
|
return
|
|
fi
|
|
|
|
# Not found.
|
|
Verbose "$f: $r not found (skip)"
|
|
}
|
|
|
|
FindPackage()
|
|
{
|
|
local f="$1" r; shift || return
|
|
|
|
for r; do
|
|
[ -n "$r" ] || continue
|
|
if [ -z "${r##/*}" ]; then
|
|
FindByPath "$f" "$r"
|
|
elif [ -n "${r##*/*}" ]; then
|
|
FindByName "$f" "$r"
|
|
else
|
|
Verbose "$f: invalid pathname $r"
|
|
fi
|
|
done
|
|
}
|