2007-03-05 01:15:05 +03:00
#!/bin/sh -efu
2002-03-25 23:37:46 +03:00
#
2007-08-08 00:49:48 +04:00
# This file provides FindPackage() function which maps paths and
# commands, such as found in shell scripts, to rpm dependencies.
#
# Usage:
2007-09-29 18:36:59 +04:00
# . @RPMCONFIGDIR@/find-package
2007-08-08 00:49:48 +04:00
# FindPackage src [path...] [command...]
#
# Arguments:
2007-09-18 23:46:02 +04:00
# src - the file being processed, used for diagnostics;
# also, if the file appears to reside under */sbin/
# directory, the PATH search order is adjusted
# so as to better match root code
2007-08-08 00:49:48 +04:00
# path - absolute path to file, e.g. /bin/cat
# command - executable expected to reside under standard
# PATH directories, e.g. cat
#
2003-04-22 19:11:52 +04:00
# Copyright (C) 2002-2003 Dmitry V. Levin <ldv@altlinux.org>
2008-01-24 22:28:01 +03:00
# Copyright (C) 2007,2008 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
2007-09-18 23:46:02 +04:00
# We use different PATHs for */sbin/ and non-/sbin scripts. However,
# the distinction is not quite reliable -- there is simply no easy way
# to discriminate between root-only and user-capable shell code. Thus
# we must use rather conservative path adjustment: 1) the set of user
# and root directories is the same, it is only the order that differs;
# 2) / has main priority over /usr, while as "bin vs sbin" distinction has
# only secondary priority. The reason is that / has only "most important"
# contents, and /usr is used virtually "for everything else", whatever it is.
# Now that / has a boost, there are simply less chances to end up with
# unrelated dependencies.
DEF_RPM_FINDPACKAGE_USER_PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin:/usr/games
DEF_RPM_FINDPACKAGE_ROOT_PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/usr/games
# RPM_FINDPACKAGE_PATH is exported by rpm-build
RPM_FINDPACKAGE_USER_PATH="$(IFS="$IFS:"; set -f; echo '' ${RPM_FINDPACKAGE_PATH-} $DEF_RPM_FINDPACKAGE_USER_PATH |sed -e 's/ */:/g; s/^://')"
RPM_FINDPACKAGE_ROOT_PATH="$(IFS="$IFS:"; set -f; echo '' ${RPM_FINDPACKAGE_PATH-} $DEF_RPM_FINDPACKAGE_ROOT_PATH |sed -e 's/ */:/g; s/^://')"
Debug "RPM_FINDPACKAGE_USER_PATH=$RPM_FINDPACKAGE_USER_PATH"
Debug "RPM_FINDPACKAGE_ROOT_PATH=$RPM_FINDPACKAGE_ROOT_PATH"
2007-03-08 21:54:08 +03:00
2008-03-17 22:19:37 +03:00
# By default, FindPackage prefers virtual (most common) dependencies,
# e.g. /usr/bin/perl -> /usr/bin/perl. This is good for executables.
# However, some binary dependencies should explicitly map to host-system
# package names, e.g. /usr/lib/libdb.so -> libdb4.4-devel. Localizing
# the following variable with non-empty value will tweak FindPackage
# to use the latter plan.
RPM_FINDPACKAGE_HOST_PKG_NAMES=
2007-08-07 21:04:23 +04:00
# Below we use 'local Verbose=Info' to increase per-case verbosity.
Verbose=Verbose
2008-01-23 01:26:43 +03:00
FindByPathUnderBuildroot()
{
local f="$1" rep="$2" xbrep; shift 2 || return
[ -n "${RPM_BUILD_ROOT-}" ] || return 0
2008-01-24 02:54:48 +03:00
MatchBuildroot()
{
[ -n "$1" ] &&
2008-02-19 03:13:51 +03:00
[ -z "${1##$RPM_BUILD_ROOT/*}" ]
2008-01-24 02:54:48 +03:00
}
StatPrint()
{
[ -e "$1" -o -L "$1" ] &&
2008-02-19 03:13:51 +03:00
printf '%s\n' "${1#$RPM_BUILD_ROOT}"
2008-01-24 02:54:48 +03:00
}
2008-01-23 01:26:43 +03:00
xbrep=$(CanonPath "$RPM_BUILD_ROOT$rep")
2008-01-24 02:54:48 +03:00
if MatchBuildroot "$xbrep"; then
2008-01-23 01:26:43 +03:00
# Good. The path was canonicalized against buildroot.
2008-01-24 02:54:48 +03:00
StatPrint "$xbrep" && return 0
2008-01-23 01:26:43 +03:00
else
# Too bad. The path was canonicalized outside buildroot.
2008-01-24 02:54:48 +03:00
# They should fix their symbolic links.
2008-01-23 01:26:43 +03:00
Warning "$f: $rep cannot be canonicalized under RPM_BUILD_ROOT"
# Consider this: RPM_BUILD_ROOT/A/B/C -> /D/C
# `-> /D
# It still makes sense to check /D/C under RPM_BUILD_ROOT.
2008-01-24 02:54:48 +03:00
xbrep=$(CanonPath "$RPM_BUILD_ROOT$xbrep")
MatchBuildroot "$xbrep" && StatPrint "$xbrep" && return 0
2008-01-23 01:26:43 +03:00
fi
2008-01-24 02:54:48 +03:00
# They might also ask if /etc/init.d/foo is under RPM_BUILD_ROOT.
# That would be /etc/rc.d/init.d/foo.
xbrep=$(CanonPath "$rep")
xbrep=$(CanonPath "$RPM_BUILD_ROOT$xbrep")
MatchBuildroot "$xbrep" && StatPrint "$xbrep" && return 0
# Not there. Not now.
:
2008-01-23 01:26:43 +03:00
}
2007-03-08 15:20:02 +03:00
FindByPath()
2002-03-25 23:37:46 +03:00
{
2007-03-08 15:20:02 +03:00
# Dependence name starts with `/'.
local f="$1" rep="$2" package; shift 2 || return
2002-03-25 23:37:46 +03:00
2007-09-21 15:58:05 +04:00
# Does it start with %_builddir or %buildroot?
if [ -n "${RPM_BUILD_DIR-}" ] && [ -z "${rep##$RPM_BUILD_DIR*}" ]; then
Info "$f: invalid dependency: $rep"
return 1
fi
2007-03-08 15:20:02 +03:00
if [ -n "${RPM_BUILD_ROOT-}" ] && [ -z "${rep##$RPM_BUILD_ROOT*}" ]; then
2007-09-21 15:58:05 +04:00
Info "$f: invalid dependency: $rep"
2007-03-08 15:20:02 +03:00
return 1
fi
2003-04-22 19:11:52 +04:00
2007-03-08 15:20:02 +03:00
# Does it belong to buildroot?
2008-01-23 01:26:43 +03:00
local xbrep
xbrep=$(FindByPathUnderBuildroot "$f" "$rep")
if [ -n "$xbrep" ]; then
# The file is under buildroot. We emit file-level dependency.
# If the file is in the same package, rpm-build will optimize
# out the dependency. Otherwise, the file is to be packaged
# into another subpackage, and we get something like more strict
# dependencies between subpackages.
if [ ! -L "$RPM_BUILD_ROOT$xbrep" -a -d "$RPM_BUILD_ROOT$xbrep" ]; then
# They require a directory. Here we do only "weak" directory
# dependencies (i.e. sometimes we prefer to omit such dependencies).
# We only need to make sure that the directory actually exists after
# install, which is the case if there are packaged files under the
# directory.
local dirfiles
if dirfiles=$(PackagedFiles |fgrep "$xbrep") &&
dirfiles=$(echo '' $dirfiles '') &&
[ -n "${dirfiles##* $xbrep *}" ] &&
[ -z "${dirfiles##* $xbrep/*}" ]; then
Warning "$f: directory $xbrep not owned by the package"
2007-11-23 12:54:37 +03:00
return 0
fi
fi
2008-01-23 01:26:43 +03:00
$Verbose "$f: $rep -> \$RPM_BUILD_ROOT$xbrep"
printf '%s\n' "$xbrep"
return 0
2007-03-08 15:20:02 +03:00
fi
2003-04-22 19:11:52 +04:00
2007-11-17 15:03:19 +03:00
# Is it an alternative? Path components can be alternatives, too.
2007-11-18 06:33:19 +03:00
local p="$rep" alt_break= alt xalt xrep
xrep=$(readlink -vm "$rep")
2007-11-17 15:03:19 +03:00
while [ -n "$p" ]; do
2007-11-17 16:55:22 +03:00
# Check each path component whether it is an alternative.
2007-11-21 17:12:03 +03:00
if [ -L "$p" ] && readlink -v "$p" |grep -qs '^/etc/alternatives/'; then
2007-11-18 06:33:19 +03:00
alt=$(CanonPath "$p")
Verbose "$f: $rep -> $p -> $alt (alternative)"
printf '%s\n' "$alt"
# Now we have to decide if this alternative should eventually
# prevent final $rep dependency resolution.
xalt=$(readlink -vm "$p")
case "$xrep" in
"$xalt")
# alternative and $rep are more or less the same
2007-11-17 15:03:19 +03:00
alt_break=1 ;;
2007-11-18 06:33:19 +03:00
"$xalt"/*)
# $rep is under alternative dir, too bad
Info "$f: alternative $alt prevents $rep dependency resolution"
2007-11-17 15:03:19 +03:00
alt_break=1 ;;
esac
fi
p=${p%/*}
done
[ -z "$alt_break" ] || return 0
2007-11-18 06:33:19 +03:00
unset p alt_break alt xalt xrep ||:
2003-04-22 19:11:52 +04:00
2007-11-18 06:33:19 +03:00
# Hard time checking $rep path components is over.
# Now we are ready to apply our know-how.
rep=$(CanonPath "$rep")
2007-08-27 21:21:55 +04:00
2007-09-23 01:15:35 +04:00
# Ignore pseudo-filesystem dependencies.
local dir="${rep#/}"; dir="${dir%%/*}"
case "$dir" in
dev | proc | sys )
$Verbose "$f: $rep -> /$dir (skip)"
return ;;
esac
unset dir
2008-03-17 22:19:37 +03:00
if [ -z "$RPM_FINDPACKAGE_HOST_PKG_NAMES" ]; then
2008-02-01 23:59:28 +03:00
# Ideally, we'd like to output all file-level dependencies here just as the are.
# However, due to current Sisyphus design (separate $arch and noarch repos),
# this can result in cross-arch "semi-unmet" dependencies. For now, we check
# if the dependency is "safe enough" to put it as is.
2008-01-24 03:21:43 +03:00
# APT can handle certain file-level dependencies as is.
case "$rep" in
*/bin/* | */sbin/* | */etc/* )
2008-02-25 23:05:04 +03:00
$Verbose "$f: $rep -> $rep (raw, APT-friendly)"
2008-01-24 03:21:43 +03:00
printf %s\\n "$rep"
return ;;
esac
2008-02-02 00:06:09 +03:00
# Check if this path is explicitly provided.
local prov n1 n2
if prov=$(rpmquery --queryformat='%{NAME}\n' --whatprovides "$rep" 2>/dev/null) &&
n1=$(echo "$prov" |wc -l) &&
n2=$(rpmquery --queryformat='%{NAME}\n' -f "$rep" 2>/dev/null |wc -l) &&
[ "$n1" -gt "$n2" ]; then
prov=$(echo "$prov" |LC_COLLATE=C sort -u)
$Verbose "$f: $rep -> $rep (raw, provided by$(echo '' $prov))"
printf %s\\n "$rep"
return
fi
2008-02-02 00:57:33 +03:00
# The path is also "safe enough" if it is already required by someone.
local req
if req=$(rpmquery --queryformat='%{NAME}\n' --whatrequires "$rep" 2>/dev/null); then
req=$(echo "$req" |LC_COLLATE=C sort -u)
$Verbose "$f: $rep -> $rep (raw, required by$(echo '' $req))"
printf %s\\n "$rep"
return
fi
find-package (FindByPath): enhanced contents_index search
In FindByPath, we should always check contents_index_bin first.
It is not quite expensive, and we make no assumptions which path
entries it may contain (our contents_index_bin, in addition
to standard *bin/ paths, also has /etc entries).
However, if contents_index_bin lookup fails, we may or may
not want to proceed with very expensive contents_index_all
search. We assume that, if contents_index_bin lookup actually
has take place for some standard *bin/ path, then there is simply
no need to proceed with contents_index_all.
Now we also assume that contents_index_all file can be possibly
gzipped (I use "gzip -cdfq" for "zcat or cat", found in zgrep).
Also increased verbosity (Verbose to Info) for contents_index_all
messages, since it is expensive and it is a means of "last resort"
to finding something strange before giving up, which is quite worth
to note about.
Also increased verbosity for "raw, not found" dependencies,
since they are likely to become unmet.
2007-08-07 17:32:46 +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)"
2007-03-08 16:49:21 +03:00
local n="$(IFS=$'\n'; set -- $package; echo $#)"
if [ "$n" = 1 ]; then
2007-08-07 21:04:23 +04:00
$Verbose "$f: $rep -> $package (via contents_index_bin)"
2007-03-08 15:20:02 +03:00
printf %s\\n "$package"
return
2007-03-08 16:49:21 +03:00
elif [ "$n" -gt 1 ]; then
Info "$f: $rep indexed by:$(echo '' $package)"
2007-08-07 21:04:23 +04:00
Info "$f: $rep -> $rep (raw, ambiguous, via contents_index_bin)"
2007-03-08 16:49:21 +03:00
printf %s\\n "$rep"
2007-03-08 15:20:02 +03:00
return
fi
find-package (FindByPath): enhanced contents_index search
In FindByPath, we should always check contents_index_bin first.
It is not quite expensive, and we make no assumptions which path
entries it may contain (our contents_index_bin, in addition
to standard *bin/ paths, also has /etc entries).
However, if contents_index_bin lookup fails, we may or may
not want to proceed with very expensive contents_index_all
search. We assume that, if contents_index_bin lookup actually
has take place for some standard *bin/ path, then there is simply
no need to proceed with contents_index_all.
Now we also assume that contents_index_all file can be possibly
gzipped (I use "gzip -cdfq" for "zcat or cat", found in zgrep).
Also increased verbosity (Verbose to Info) for contents_index_all
messages, since it is expensive and it is a means of "last resort"
to finding something strange before giving up, which is quite worth
to note about.
Also increased verbosity for "raw, not found" dependencies,
since they are likely to become unmet.
2007-08-07 17:32:46 +04:00
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.
2007-08-07 21:04:23 +04:00
local Verbose=Info
find-package (FindByPath): enhanced contents_index search
In FindByPath, we should always check contents_index_bin first.
It is not quite expensive, and we make no assumptions which path
entries it may contain (our contents_index_bin, in addition
to standard *bin/ paths, also has /etc entries).
However, if contents_index_bin lookup fails, we may or may
not want to proceed with very expensive contents_index_all
search. We assume that, if contents_index_bin lookup actually
has take place for some standard *bin/ path, then there is simply
no need to proceed with contents_index_all.
Now we also assume that contents_index_all file can be possibly
gzipped (I use "gzip -cdfq" for "zcat or cat", found in zgrep).
Also increased verbosity (Verbose to Info) for contents_index_all
messages, since it is expensive and it is a means of "last resort"
to finding something strange before giving up, which is quite worth
to note about.
Also increased verbosity for "raw, not found" dependencies,
since they are likely to become unmet.
2007-08-07 17:32:46 +04:00
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
2008-03-17 22:19:37 +03:00
fi # RPM_FINDPACKAGE_HOST_PKG_NAMES
2007-03-08 15:20:02 +03:00
# Check package database.
2007-08-08 02:54:04 +04:00
if package="$(rpmquery --whatprovides --queryformat='%{NAME}\n' -- "$rep" 2>/dev/null)"; then
2007-03-08 15:20:02 +03:00
package="$(printf %s "$package" |LC_COLLATE=C sort -u)"
local n="$(IFS=$'\n'; set -- $package; echo $#)"
if [ "$n" = 1 ]; then
2007-08-07 21:04:23 +04:00
$Verbose "$f: $rep -> $package (via rpmdb)"
2007-03-08 15:20:02 +03:00
printf %s\\n "$package"
return
elif [ "$n" -gt 1 ]; then
Info "$f: $rep provided by:$(echo '' $package)"
2007-08-07 21:04:23 +04:00
Info "$f: $rep -> $rep (raw, ambiguous, via rpmdb)"
2007-03-08 16:49:21 +03:00
printf %s\\n "$rep"
return
2007-03-08 15:20:02 +03:00
fi
fi
2003-04-22 19:11:52 +04:00
2007-03-08 15:20:02 +03:00
# Not found; output raw dependence.
find-package (FindByPath): enhanced contents_index search
In FindByPath, we should always check contents_index_bin first.
It is not quite expensive, and we make no assumptions which path
entries it may contain (our contents_index_bin, in addition
to standard *bin/ paths, also has /etc entries).
However, if contents_index_bin lookup fails, we may or may
not want to proceed with very expensive contents_index_all
search. We assume that, if contents_index_bin lookup actually
has take place for some standard *bin/ path, then there is simply
no need to proceed with contents_index_all.
Now we also assume that contents_index_all file can be possibly
gzipped (I use "gzip -cdfq" for "zcat or cat", found in zgrep).
Also increased verbosity (Verbose to Info) for contents_index_all
messages, since it is expensive and it is a means of "last resort"
to finding something strange before giving up, which is quite worth
to note about.
Also increased verbosity for "raw, not found" dependencies,
since they are likely to become unmet.
2007-08-07 17:32:46 +04:00
Info "$f: $rep -> $rep (raw, not found)"
2007-03-08 15:20:02 +03:00
printf %s\\n "$rep"
}
2003-04-22 19:11:52 +04:00
2007-03-08 15:20:02 +03:00
FindByName()
{
local f="$1" r="$2" rep package; shift 2 || return
2003-04-22 19:11:52 +04:00
2007-09-19 10:31:17 +04:00
local dir="${f%/*}"; dir="${dir#${RPM_BUILD_ROOT-}}"
2007-09-18 23:46:02 +04:00
local findpackage_path="$RPM_FINDPACKAGE_USER_PATH"
2007-09-19 10:31:17 +04:00
case "$dir" in
2008-02-02 01:21:10 +03:00
*/sbin | "" ) # %buildroot dir is used to save scriptlets
2007-09-19 10:31:17 +04:00
findpackage_path="$RPM_FINDPACKAGE_ROOT_PATH" ;;
/etc/*)
dir="${dir#/etc/}"; dir="${dir%%/*}"
case "$dir" in
# The sbin-ish places. WARNING: Explicit Content!
rc.d | init.d | control.d | chroot.d | net | ppp | cron* | hotplug* )
Debug "$f: root PATH on"
findpackage_path="$RPM_FINDPACKAGE_ROOT_PATH" ;;
esac
;;
2007-09-18 23:46:02 +04:00
esac
2007-09-19 10:31:17 +04:00
unset dir
2007-09-18 23:46:02 +04:00
2007-03-08 15:20:02 +03:00
# Check buildroot first.
if [ -n "${RPM_BUILD_ROOT-}" ]; then
2007-09-19 12:17:43 +04:00
rep=$(IFS="$IFS:"; set -f
for dir in $findpackage_path; do
rep="$dir/$r"
BR_rep="$RPM_BUILD_ROOT/$rep"
if [ -f "$BR_rep" -o -L "$BR_rep" ]; then
printf '%s\n' "$rep"
break
fi
done)
if [ -n "$rep" ]; then
2007-12-03 12:06:58 +03:00
$Verbose "$f: $r -> \$RPM_BUILD_ROOT$rep"
printf '%s\n' "$rep"
2007-03-08 15:20:02 +03:00
return
fi
fi
2003-04-22 19:11:52 +04:00
2007-03-08 15:20:02 +03:00
# Check for pkg contents binary index.
2007-08-08 00:18:21 +04:00
local save_rep= save_package=
2007-03-08 15:20:02 +03:00
if [ -n "${RPM_PKG_CONTENTS_INDEX_BIN-}" ] && [ -s "$RPM_PKG_CONTENTS_INDEX_BIN" ] && [ -r "$RPM_PKG_CONTENTS_INDEX_BIN" ]; then
2007-09-18 23:46:02 +04:00
local out="$(awk -v r="$r" -v findpackage_path="$findpackage_path" '
2007-03-08 21:54:08 +03:00
BEGIN {
2007-08-07 22:41:19 +04:00
# Here we enumerate all possible paths to keep the order;
# later we sort the result with "sort -n".
2007-09-18 23:46:02 +04:00
n = split(findpackage_path, ary, ":")
2007-03-08 21:54:08 +03:00
for (i = 1; i <= n; i++) {
dir = ary[i]
sub("/+$", "", dir)
2007-03-11 23:40:37 +03:00
file = dir "/" r
if (dir && !(file in FILES))
FILES[file] = i
2007-03-08 21:54:08 +03:00
}
2007-08-07 22:41:19 +04:00
# By now FILES is normally something like this:
# /bin/r 1
# /sbin/r 2
# /usr/bin/r 3
# /usr/sbin/r 4
# ...
2007-03-08 21:54:08 +03:00
}
2007-03-11 23:40:37 +03:00
NF==2 && ($1 in FILES) {
2007-08-07 22:41:19 +04:00
# Possible output is like this:
# 3 /usr/bin/r pkgA
# 1 /bin/r pkgB
2007-03-11 23:40:37 +03:00
print FILES[$1] "\t" $1 "\t" $2
2007-03-08 21:54:08 +03:00
}
' "$RPM_PKG_CONTENTS_INDEX_BIN" |
2007-08-07 22:59:50 +04:00
# Best paths go first:
sort -n |
# For each package, keep only the best path:
sort -u -k3 |
# Best paths still go first:
sort -n |
# Well done, discard numbers.
cut -f2-)"
2007-03-08 18:26:28 +03:00
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")"
2007-09-12 19:28:46 +04:00
$Verbose "$f: $r -> $rep -> $package (via contents_index_bin)"
2007-03-08 18:26:28 +03:00
printf %s\\n "$package"
return
elif [ "$n" -gt 1 ]; then
2007-08-08 00:18:21 +04:00
# Content index search produced a confict: we have 2 or more paths
# from different packages. Consider this case:
# /usr/bin/r pkgA
# /usr/bin/r pkgB
# /usr/sbin/r pkgC
2007-08-10 16:08:53 +04:00
# Remember that best paths go first, and each package has only the best path.
2007-08-08 00:18:21 +04:00
# Now if the first two paths are the same, we produce raw dependency on /usr/bin/r.
2007-08-07 21:04:23 +04:00
local Verbose=Info
2007-03-08 18:26:28 +03:00
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")"
2007-08-10 16:08:53 +04:00
# Actually our contents_index generator already handles path dups,
# so the above example is likely to transform into this:
# /usr/bin/r /usr/bin/r
# /usr/sbin/r pkgC
# So we first check if path = package.
if [ "$rep" = "$package" ]; then
Info "$f: $r -> $rep -> $rep (ambiguous, via contents_index_bin)"
printf %s\\n "$rep"
return
fi
# And then we check if the first two paths are the same.
2007-03-08 18:26:28 +03:00
local rep2="$(IFS=$'\t\n'; set -- $out; printf %s "$3")"
if [ "$rep" = "$rep2" ]; then
2007-08-07 21:04:23 +04:00
Info "$f: $r -> $rep -> $rep (raw, ambiguous, via contents_index_bin)"
2007-03-08 18:26:28 +03:00
printf %s\\n "$rep"
return
2002-03-25 23:37:46 +03:00
fi
2007-08-10 16:08:53 +04:00
# However, consider yet worse real-life case:
2007-08-08 00:18:21 +04:00
# /usr/bin/arpsend arpsend
# /usr/sbin/arpsend vzctl
# In this case, we perfer to put aside the conflict for a while, and query
# the host system first. There's a good chance that the right package, either
# arpsend or vzctl, IS installed, and other unrelated packages are NOT installed.
2007-09-19 12:17:43 +04:00
# However, if the host system does not provide any candidate, we have to produce
# the dependency on /usr/bin/arpsend -> arpsend.
2007-08-08 00:18:21 +04:00
save_rep="$rep" save_package="$package"
2007-03-08 18:26:28 +03:00
fi
2007-03-08 15:20:02 +03:00
fi
2007-03-08 16:18:41 +03:00
# Lookup in the host system.
2007-09-19 12:17:43 +04:00
rep=$(IFS="$IFS:"; set -f
for dir in $findpackage_path; do
rep="$dir/$r"
if [ -f "$rep" ]; then
printf '%s\n' "$rep"
fi
done)
if [ -n "$rep" ]; then
2007-03-08 16:18:41 +03:00
local n="$(IFS=$'\n'; set -- $rep; echo $#)"
if [ "$n" -gt 1 ]; then
2007-09-19 12:17:43 +04:00
# We've got a few paths, e.g. awk -> {/bin/awk,/usr/bin/awk};
2007-08-08 00:18:21 +04:00
# we check if all paths really point to the same file.
2007-03-08 16:18:41 +03:00
n="$(IFS=$'\n'; for f in $rep; do readlink -vm "$f"; done |sort -u |wc -l)"
2007-08-07 21:04:23 +04:00
if [ "$n" -gt 1 ]; then
local Verbose=Info
2007-09-19 12:17:43 +04:00
Info "$f: host_env $r:$(echo '' $rep)"
2007-08-07 21:04:23 +04:00
fi
2007-08-08 00:18:21 +04:00
# But we select the first path, which is the best, anyway.
2007-03-08 16:18:41 +03:00
rep="$(IFS=$'\n'; set -- $rep; printf %s "$1")"
fi
if [ -n "$rep" ]; then
2007-09-19 12:17:43 +04:00
$Verbose "$f: $r -> $rep -> ... (via host_env)"
2007-03-08 16:18:41 +03:00
FindByPath "$f" "$rep"
2007-03-08 15:20:02 +03:00
return
fi
fi
2007-08-08 00:18:21 +04:00
# Reconsult package binary index.
if [ -n "$save_rep" ] && [ -n "$save_package" ]; then
rep="$save_rep" package="$save_package"
2007-08-07 21:04:23 +04:00
$Verbose "$f: $r -> $rep -> $package (via contents_index_bin)"
2007-03-08 23:31:55 +03:00
printf %s\\n "$package"
return
fi
2007-03-08 15:20:02 +03:00
# Not found.
2007-09-19 11:08:53 +04:00
local maybe_function=
case "$r" in
2007-10-09 12:30:05 +04:00
*[!A-Za-z0-9_]*) ;;
[!A-Za-z_]*) ;;
2007-09-19 11:08:53 +04:00
*[A-Z_]*) maybe_function=1 ;;
esac
if [ -n "$maybe_function" ]; then
$Verbose "$f: $r not found (skip, maybe function)"
else
Info "$f: $r not found (skip)"
fi
2007-03-08 15:20:02 +03:00
}
2007-03-06 21:08:06 +03:00
2007-03-08 15:20:02 +03:00
FindPackage()
{
local f="$1" r; shift || return
for r; do
2007-08-07 21:04:23 +04:00
local Verbose=Verbose
2007-09-10 13:26:52 +04:00
# Only these characters are allowed for pathnames or commands:
valid='A-Za-z0-9/@=.,:_+-'
2007-08-07 20:41:04 +04:00
case "$r" in
2007-09-12 20:07:43 +04:00
/*[!$valid]*)
2007-09-10 13:26:52 +04:00
Info "$f: invalid pathname: $r" ;;
2007-11-23 11:51:32 +03:00
/*[!/.]*)
2007-08-07 20:41:04 +04:00
FindByPath "$f" "$r" ;;
*/*)
2007-09-10 13:26:52 +04:00
Info "$f: invalid pathname: $r" ;;
2007-08-07 20:41:04 +04:00
-*)
2007-09-10 13:26:52 +04:00
Info "$f: invalid command: $r" ;;
2007-09-12 20:07:43 +04:00
*[!$valid]*)
2007-09-10 13:26:52 +04:00
Info "$f: invalid command: $r" ;;
2007-08-07 20:41:04 +04:00
'')
2007-09-12 19:32:59 +04:00
Verbose "$f: empty command?" ;;
2007-08-07 20:41:04 +04:00
*)
FindByName "$f" "$r" ;;
esac
2002-03-25 23:37:46 +03:00
done
}