|
|
#!/bin/sh |
#!/bin/bash |
# Copyright 1999-2005 Gentoo Foundation |
# Copyright 1999-2007 Gentoo Foundation |
# $Header$ |
|
| |
# revdep-rebuild: Reverse dependency rebuilder. | # revdep-rebuild: Reverse dependency rebuilder. |
# Original Author: Stanislav Brabec | # Original Author: Stanislav Brabec |
# Current Maintainer: Paul Varner <fuzzyray@gentoo.org> | # Current Maintainer: Paul Varner <fuzzyray@gentoo.org> |
| |
# Known problems: |
source /etc/init.d/functions.sh |
# |
# TODO: |
# In exact ebuild mode revdep-rebuild can fail to properly order packages, |
# - Use more /etc/init.d/functions.sh |
# which are not up to date. |
|
# http://bugs.gentoo.org/show_bug.cgi?id=23018 |
|
# |
|
# Rebuilding using --package-names mode should be default, but emerge has no |
|
# feature to update to latest version of defined SLOT. |
|
# http://bugs.gentoo.org/show_bug.cgi?id=4698 |
|
| |
# Customizable variables: | # Customizable variables: |
# | # |
|
|
# An entry of "-*" means to clear the variable from that point forward. | # An entry of "-*" means to clear the variable from that point forward. |
# Example: env SEARCH_DIRS="/usr/bin -*" revdep-rebuild will set SEARCH_DIRS | # Example: env SEARCH_DIRS="/usr/bin -*" revdep-rebuild will set SEARCH_DIRS |
# to contain only /usr/bin | # to contain only /usr/bin |
|
declare -r oIFS="$IFS" |
|
|
rm() { | rm() { |
[[ $LIST && $appname ]] || | [[ $LIST && $appname ]] || |
die 1 '$LIST or $appname is not defined! (This is a bug.)' | die 1 '$LIST or $appname is not defined! (This is a bug.)' |
|
|
| |
-h, --help Print this usage | -h, --help Print this usage |
-k, --keep-temp Do not delete temporary files on exit | -k, --keep-temp Do not delete temporary files on exit |
-X, --package-names Emerge based on package names, not exact versions |
-e, --exact Emerge based on exact package version |
-L, --library NAME Emerge existing packages that use the library with NAME |
|
--library=NAME NAME can be a full path to the library or a basic |
|
regular expression (man grep) |
|
-l, --no-ld-path Do not set LD_LIBRARY_PATH | -l, --no-ld-path Do not set LD_LIBRARY_PATH |
-C, --nocolor Turn off colored output | -C, --nocolor Turn off colored output |
-i, --ignore Ignore temporary files from previous runs | -i, --ignore Ignore temporary files from previous runs |
|
-o, --no-order Do not check the build order |
|
(Saves time, but may cause breakage.) |
-q, --quiet Be less verbose (also passed to emerge command) | -q, --quiet Be less verbose (also passed to emerge command) |
-v, --verbose Be more verbose | -v, --verbose Be more verbose |
|
-u, --no-util UTIL Do not use features provided by UTIL |
|
--no-util=UTIL UTIL can be one of portage-utils, pkgcore, or equery |
|
or it can be a *quoted* space-delimited list. |
|
-L, --library NAME Emerge existing packages that use the library with NAME |
|
--library=NAME NAME can be a full path to the library or a basic |
|
regular expression (man grep) |
| |
Calls emerge, all other options are used for it (e. g. -p, --pretend). | Calls emerge, all other options are used for it (e. g. -p, --pretend). |
| |
|
|
die() { | die() { |
local status=$1 | local status=$1 |
shift | shift |
echo "$@" >&2 |
eerror "$@" |
exit $status | exit $status |
} | } |
# Set the output color |
# What to do when dynamic linking is consistent |
set_color() { |
clean_exit() { |
# sets itself the first time it's called, so we don't have to check $NOCOLOR |
[[ $KEEP_TEMP ]] || rm $LIST.?_* |
# each time |
set_color green |
if [[ $NOCOLOR ]]; then |
die 0 $'\n'"$OK_TEXT... All done. " |
set_color() { :; } |
|
else |
|
set_color() { |
|
case $1 in |
|
black) tput setaf 0;; |
|
maroon) tput setaf 1;; |
|
green) tput setaf 2;; |
|
tan) tput setaf 3;; |
|
blue) tput setaf 4;; |
|
magenta) tput setaf 5;; |
|
aqua) tput setaf 6;; |
|
gray) tput setaf 7;; |
|
red) tput setaf 8;; |
|
*) tput setaf 9;; |
|
esac |
|
} |
|
set_color "$@" |
|
fi |
|
} |
|
# Echo with a particular color |
|
color_echo() { |
|
set_color $1 |
|
shift |
|
echo "$@" |
|
set_color normal |
|
} | } |
get_args() { | get_args() { |
appname="${0##*/}" | appname="${0##*/}" |
# Check if various utils are installed |
echo_v() { ewarn "$@"; } |
# TODO: give the user the option to turn off detection of various utils? |
unset VERBOSE KEEP_TEMP EMERGE_OPTIONS remove_old_tempfiles |
if hash q 2> /dev/null; then |
order_packages=1 |
PORTAGE_UTILS=1 |
PACKAGE_NAMES=1 |
elif hash pquery 2> /dev/null; then |
|
PKGCORE=1 |
|
elif hash equery 2> /dev/null; then |
|
# Well... if equery doesn't work something's definitely broken ;) |
|
EQUERY=1 |
|
fi |
|
echo_v() { echo "$@"; } |
|
unset PACKAGE_NAMES VERBOSE KEEP_TEMP EMERGE_OPTIONS CALLED_OPTIONS |
|
SONAME="not found" | SONAME="not found" |
SEARCH_BROKEN=1 | SEARCH_BROKEN=1 |
FULL_LD_PATH=1 | FULL_LD_PATH=1 |
|
local avoid_utils |
while [[ $1 ]]; do | while [[ $1 ]]; do |
case $1 in | case $1 in |
-h|--help) | -h|--help) |
print_usage | print_usage |
exit 0 | exit 0 |
;; | ;; |
-X|--package-names) |
-e|--exact) |
PACKAGE_NAMES=1 |
unset PACKAGE_NAMES |
CALLED_OPTIONS+=" --package_names" # TODO: inconsistency _ versus - ? |
;; |
|
-o|--no-order) |
|
unset order_packages |
;; | ;; |
-q|--quiet) | -q|--quiet) |
echo_v() { : ; } | echo_v() { : ; } |
quiet=1 | quiet=1 |
EMERGE_OPTIONS+=" $1" |
EMERGE_OPTIONS+=($1) |
;; | ;; |
-L=*|--library=*|--soname=*|--soname-regexp=*) | -L=*|--library=*|--soname=*|--soname-regexp=*) |
SONAME="${1#*=}" | SONAME="${1#*=}" |
unset SEARCH_BROKEN | unset SEARCH_BROKEN |
CALLED_OPTIONS+=" --library=$SONAME" |
|
;; | ;; |
-L|--library|--soname|--soname-regexp) | -L|--library|--soname|--soname-regexp) |
[[ $2 = -* ]] && die 1 "Missing expected argument to $1" |
[[ ! $2 || $2 = -* ]] && die 1 "Missing expected argument to $1" |
shift | shift |
SONAME="$1" | SONAME="$1" |
unset SEARCH_BROKEN | unset SEARCH_BROKEN |
CALLED_OPTIONS+=" --library=$SONAME" |
;; |
|
-u=*|--no-util=*) |
|
# TODO: check for invalid values |
|
avoid_utils="${1#*=}" |
|
;; |
|
-u|--no-util) |
|
[[ ! $2 || $2 = -* ]] && die 1 "Missing expected argument to $1" |
|
shift |
|
avoid_utils="$1" |
;; | ;; |
-nc|-C|--no-color|--nocolor) | -nc|-C|--no-color|--nocolor) |
NOCOLOR=1 |
# TODO: Does this variable do anything now that the main color functions are removed? |
|
export NOCOLOR=1 |
;; | ;; |
-l|-np|--no-ld-path) | -l|-np|--no-ld-path) |
unset FULL_LD_PATH | unset FULL_LD_PATH |
CALLED_OPTIONS+=" --no-ld-path" |
|
;; | ;; |
-i|--ignore) | -i|--ignore) |
rm -f $LIST* |
remove_old_tempfiles=1 |
;; | ;; |
-k|--keep-temp) | -k|--keep-temp) |
KEEPTEMP=1 |
KEEP_TEMP=1 |
;; | ;; |
-vv|--extra-verbose|-v|--verbose) | -vv|--extra-verbose|-v|--verbose) |
VERBOSE=1 | VERBOSE=1 |
|
EMERGE_OPTIONS+=($1) |
;; | ;; |
--) | --) |
;; | ;; |
*) | *) |
EMERGE_OPTIONS+=" $1" |
EMERGE_OPTIONS+=($1) |
;; | ;; |
esac | esac |
shift | shift |
done | done |
|
# Check if various utils are allowed and installed |
|
if [[ $avoid_utils != *portage-utils* ]] && hash q 2> /dev/null; then |
|
PORTAGE_UTILS=1 |
|
elif [[ $avoid_utils != *pkgcore* ]] && hash pquery 2> /dev/null; then |
|
PKGCORE=1 |
|
elif [[ $avoid_utils != *equery* ]] && hash equery 2> /dev/null; then |
|
EQUERY=1 |
|
fi |
|
EMERGE_OPTIONS=(${EMERGE_OPTIONS[@]/%-p/--pretend}) |
|
EMERGE_OPTIONS=(${EMERGE_OPTIONS[@]/%-f/--fetchonly}) |
|
if [[ ${EMERGE_OPTIONS[@]} != *--pretend* && $UID -ne 0 ]]; then |
|
ewarn "You are not superuser. Adding --pretend to emerge options." |
|
EMERGE_OPTIONS+=(--pretend) |
|
fi |
} | } |
|
is_real_merge() [[ |
|
${EMERGE_OPTIONS[@]} != *--pretend* && ${EMERGE_OPTIONS[@]} != *--fetchonly* |
|
]] |
|
|
get_args "$@" | get_args "$@" |
| |
echo "Configuring search environment for $appname" |
einfo "Configuring search environment for $appname" |
| |
# Obey PORTAGE_NICENESS | # Obey PORTAGE_NICENESS |
PORTAGE_NICENESS=$(portageq envvar PORTAGE_NICENESS) | PORTAGE_NICENESS=$(portageq envvar PORTAGE_NICENESS) |
|
|
fi | fi |
| |
# Get the ROOTPATH and PATH from /etc/profile.env | # Get the ROOTPATH and PATH from /etc/profile.env |
if [[ -r "/etc/profile.env" ]]; then |
if [[ -rs "/etc/profile.env" ]]; then |
SEARCH_DIRS+=" "$(. /etc/profile.env; /usr/bin/tr ':' ' ' <<< "$ROOTPATH $PATH") | SEARCH_DIRS+=" "$(. /etc/profile.env; /usr/bin/tr ':' ' ' <<< "$ROOTPATH $PATH") |
fi | fi |
| |
# Get the directories from /etc/ld.so.conf | # Get the directories from /etc/ld.so.conf |
if [[ -r /etc/ld.so.conf ]]; then |
if [[ -rs /etc/ld.so.conf ]]; then |
SEARCH_DIRS+=" "$(sed '/^#/d;s/#.*$//' /etc/ld.so.conf) | SEARCH_DIRS+=" "$(sed '/^#/d;s/#.*$//' /etc/ld.so.conf) |
fi | fi |
| |
# Set the final variables | # Set the final variables |
|
[[ $SEARCH_DIRS ]] || die 1 "No search defined -- this is a bug." |
SEARCH_DIRS=$(clean_var "$SEARCH_DIRS") | SEARCH_DIRS=$(clean_var "$SEARCH_DIRS") |
SEARCH_DIRS_MASK=$(clean_var "$SEARCH_DIRS_MASK") | SEARCH_DIRS_MASK=$(clean_var "$SEARCH_DIRS_MASK") |
LD_LIBRARY_MASK=$(clean_var "$LD_LIBRARY_MASK") | LD_LIBRARY_MASK=$(clean_var "$LD_LIBRARY_MASK") |
|
|
if [[ $LIST = .$appname ]]; then | if [[ $LIST = .$appname ]]; then |
die 1 "!!! Unable to find a satisfactory location for temporary files !!!" | die 1 "!!! Unable to find a satisfactory location for temporary files !!!" |
fi | fi |
|
[[ $remove_old_tempfiles ]] && rm -f $LIST.* |
| |
CALLED_OPTIONS=$(clean_var "$CALLED_OPTIONS") |
|
function set_trap () { | function set_trap () { |
trap "rm_temp $1" SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM | trap "rm_temp $1" SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM |
} | } |
function rm_temp () { | function rm_temp () { |
rm $1 | rm $1 |
die 1 $' ...terminated.\nRemoving incomplete '"$1." |
die 1 $' ...terminated. Removing incomplete '"$1." |
} | } |
if [[ $SEARCH_BROKEN ]]; then |
get_search_env() { |
|
if [[ $SEARCH_BROKEN ]]; then |
SONAME_SEARCH="$SONAME" | SONAME_SEARCH="$SONAME" |
HEAD_TEXT="broken by a package update" | HEAD_TEXT="broken by a package update" |
OK_TEXT="Dynamic linking on your system is consistent" | OK_TEXT="Dynamic linking on your system is consistent" |
WORKING_TEXT=" consistency" |
WORKING_TEXT="consistency" |
else |
else |
# first case is needed to test against /path/to/foo.so | # first case is needed to test against /path/to/foo.so |
if [[ $SONAME = /* ]]; then | if [[ $SONAME = /* ]]; then |
# Set to "<space>$SONAME<space>" | # Set to "<space>$SONAME<space>" |
|
|
HEAD_TEXT="using $SONAME" | HEAD_TEXT="using $SONAME" |
OK_TEXT="There are no dynamic links to $SONAME" | OK_TEXT="There are no dynamic links to $SONAME" |
unset WORKING_TEXT SOMD5 | unset WORKING_TEXT SOMD5 |
fi |
fi |
| |
[[ $LIST ]] || die 1 $LIST IS NOT DEFINED |
[[ $LIST ]] || die 1 $LIST IS NOT DEFINED |
| |
# If any of our temporary files are older than 1 day, remove them all |
# If any of our temporary files are older than 1 day, remove them all |
[[ ! $keep_tempfiles && -r $LIST && |
[[ ! $keep_tempfiles && -r $LIST && |
$( | $( |
find -L "$LIST" -type f -mmin +1440 -print | | find -L "$LIST" -type f -mmin +1440 -print | |
while read; do echo 1; break; done | while read; do echo 1; break; done |
) ]] && rm -f $LIST* |
) ]] && rm -f $LIST.* |
|
|
# Don't use our previous files if environment doesn't match |
|
if [[ -r $LIST.0_env ]]; then |
|
oIFS="$IFS"; IFS=$'\a' |
|
PREVS=( $( |
|
source "$LIST.0_env" |
|
echo "$SEARCH_DIRS"$'\a'"$SEARCH_DIRS_MASK"$'\a'"$LD_LIBRARY_MASK"$'\a'"$PORTAGE_ROOT"$'\a'"$CALLED_OPTIONS" |
|
) ) |
|
IFS="$oIFS" |
|
if [[ ${PREVS[0]} != $SEARCH_DIRS || |
|
${PREVS[1]} != $SEARCH_DIRS_MASK || |
|
${PREVS[2]} != $LD_LIBRARY_MASK || |
|
${PREVS[3]} != $PORTAGE_ROOT || |
|
${PREVS[4]} != $CALLED_OPTIONS ]]; then |
|
echo 'Environment mismatch from previous run, deleting temporary files...' |
|
rm -f $LIST* |
|
fi |
|
unset PREVS |
|
fi |
|
| |
# Log the current environment |
# Compare old and new environments |
cat > "$LIST.0_env" <<- EOF |
# Don't use our previous files if environment doesn't match |
|
new_env=$( |
|
cat <<- EOF |
SEARCH_DIRS="$SEARCH_DIRS" | SEARCH_DIRS="$SEARCH_DIRS" |
SEARCH_DIRS_MASK="$SEARCH_DIRS_MASK" | SEARCH_DIRS_MASK="$SEARCH_DIRS_MASK" |
LD_LIBRARY_MASK="$LD_LIBRARY_MASK" | LD_LIBRARY_MASK="$LD_LIBRARY_MASK" |
PORTAGE_ROOT="$PORTAGE_ROOT" | PORTAGE_ROOT="$PORTAGE_ROOT" |
CALLED_OPTIONS="$CALLED_OPTIONS" |
EMERGE_OPTIONS="${EMERGE_OPTIONS[@]}" |
EMERGE_OPTIONS="$EMERGE_OPTIONS" |
order_packages="$order_packages" |
EOF |
FULL_LD_PATH="$FULL_LD_PATH" |
|
EOF |
if [[ $VERBOSE ]]; then |
) |
echo |
if [[ -rs $LIST.0_env ]]; then |
echo "$appname environment:" |
old_env=$(<"$LIST.0_env") |
cat $LIST.0_env |
if [[ $old_env != $new_env ]]; then |
fi |
ewarn 'Environment mismatch from previous run, deleting temporary files...' |
|
rm -f "$LIST"* |
cat <<- EOF |
fi |
|
else |
Checking reverse dependencies... |
# No 0_env file found, silently delete any other tempfiles that may exist |
|
rm -f "$LIST"* |
|
fi |
| |
Packages containing binaries and libraries $HEAD_TEXT |
# Save the environment in a file for next time |
will be emerged. |
echo "$new_env" > "$LIST.0_env" |
| |
EOF |
[[ $VERBOSE ]] && echo $'\n'"$appname environment:"$'\n'"$new_env" |
color_echo green -n "Collecting system binaries and libraries..." |
unset new_env |
| |
if [[ -r $LIST.1_files ]]; then |
echo |
echo " using existing $LIST.1_files." |
einfo "Checking reverse dependencies" |
else |
einfo "Packages containing binaries and libraries $HEAD_TEXT" |
|
einfo "will be emerged." |
|
} |
|
get_files() { |
|
einfo "Collecting system binaries and libraries" |
|
if [[ -rs $LIST.1_files ]]; then |
|
einfo "Found existing $LIST.1_files" |
|
else |
# Be safe and remove any extraneous temporary files | # Be safe and remove any extraneous temporary files |
rm -f $LIST.[1-9]_* | rm -f $LIST.[1-9]_* |
| |
set_trap "$LIST.1_*" | set_trap "$LIST.1_*" |
| |
|
if [[ $SEARCH_DIRS_MASK ]]; then |
findMask=($SEARCH_DIRS_MASK) | findMask=($SEARCH_DIRS_MASK) |
findMask="${findMask[@]/#/-o -path }" | findMask="${findMask[@]/#/-o -path }" |
findMask="${findMask#-o }" |
findMask="( ${findMask#-o } ) -prune -o" |
find ${SEARCH_DIRS[@]} \( $findMask \) -prune -o -type f \( -executable -o \ |
fi |
|
find ${SEARCH_DIRS[@]} $findMask -type f \( -executable -o \ |
-name '*.so' -o -name '*.so.*' -o -name '*.la' \) -print 2> /dev/null | | -name '*.so' -o -name '*.so.*' -o -name '*.la' \) -print 2> /dev/null | |
sort -u > $LIST.1_files |
sort -u > "$LIST.1_files" || |
echo -e " done.\n ($LIST.1_files)" |
die $? "find failed to list binary files (This is a bug.)" |
fi |
einfo "Generated new $LIST.1_files" |
|
fi |
if [[ $SEARCH_BROKEN && $FULL_LD_PATH ]]; then |
} |
echo |
get_ldpath() { |
color_echo green -n 'Collecting complete LD_LIBRARY_PATH...' |
[[ $SEARCH_BROKEN && $FULL_LD_PATH ]] || return |
if [[ -f $LIST.2_ldpath ]] ; then |
einfo 'Collecting complete LD_LIBRARY_PATH' |
echo " using existing $LIST.2_ldpath." |
if [[ -rs $LIST.2_ldpath ]] ; then |
|
einfo "Found existing $LIST.2_ldpath." |
COMPLETE_LD_LIBRARY_PATH=$(<"$LIST.2_ldpath") | COMPLETE_LD_LIBRARY_PATH=$(<"$LIST.2_ldpath") |
else | else |
set_trap "$LIST.2_ldpath" | set_trap "$LIST.2_ldpath" |
|
|
$(sed '/^#/d;s/#.*$//' < /etc/ld.so.conf) | $(sed '/^#/d;s/#.*$//' < /etc/ld.so.conf) |
$(sed 's:/[^/]*$::' < "$LIST.1_files" | sort -ru) | $(sed 's:/[^/]*$::' < "$LIST.1_files" | sort -ru) |
) | ) |
oIFS="$IFS"; IFS=':' |
IFS=':' |
COMPLETE_LD_LIBRARY_PATH="${COMPLETE_LD_LIBRARY_PATH[*]}" | COMPLETE_LD_LIBRARY_PATH="${COMPLETE_LD_LIBRARY_PATH[*]}" |
IFS="$oIFS" | IFS="$oIFS" |
echo "$COMPLETE_LD_LIBRARY_PATH" > "$LIST.2_ldpath" | echo "$COMPLETE_LD_LIBRARY_PATH" > "$LIST.2_ldpath" |
echo -e " done.\n ($LIST.2_ldpath)" |
einfo "Generated new $LIST.2_ldpath" |
fi | fi |
fi |
} |
|
main_checks() { |
echo |
einfo "Checking dynamic linking $WORKING_TEXT" |
color_echo green -n "Checking dynamic linking$WORKING_TEXT..." |
if [[ -rs $LIST.3_rebuild ]]; then |
if [[ -f $LIST.3_rebuild ]]; then |
einfo "Found existing $LIST.3_rebuild." |
echo " using existing $LIST.3_rebuild." |
else |
else |
|
[[ $LIST ]] || die 1 "$LIST" 'is undefined! (This is a bug.)' | [[ $LIST ]] || die 1 "$LIST" 'is undefined! (This is a bug.)' |
echo_v |
|
set_trap "$LIST.3_rebuild" | set_trap "$LIST.3_rebuild" |
rm -f $LIST.3* | rm -f $LIST.3* |
files=($(<"$LIST.1_files")) | files=($(<"$LIST.1_files")) |
|
|
# (special add ons are rare). | # (special add ons are rare). |
ldd_output=$(ldd "$FILE" 2>> "$LIST.3_ldd_errors" | sort -u) | ldd_output=$(ldd "$FILE" 2>> "$LIST.3_ldd_errors" | sort -u) |
ldd_status=$? # TODO: Check this for problems with sort | ldd_status=$? # TODO: Check this for problems with sort |
if grep -vF "$LD_LIBRARY_MASK" <<< "$ldd_output" | |
# HACK: if LD_LIBRARY_MASK is null or undefined grep -vF doesn't work |
|
if grep -vF "${LD_LIBRARY_MASK:=$'\a'}" <<< "$ldd_output" | |
grep -q "$SONAME_SEARCH"; then | grep -q "$SONAME_SEARCH"; then |
if [[ $SEARCH_BROKEN && $FULL_LD_PATH ]]; then | if [[ $SEARCH_BROKEN && $FULL_LD_PATH ]]; then |
| |
if LD_LIBRARY_PATH="$COMPLETE_LD_LIBRARY_PATH" ldd "$FILE" 2>/dev/null | | if LD_LIBRARY_PATH="$COMPLETE_LD_LIBRARY_PATH" ldd "$FILE" 2>/dev/null | |
grep -v "$LD_LIBRARY_MASK" | grep -q "$SONAME_SEARCH"; then |
grep -vF "$LD_LIBRARY_MASK" | grep -q "$SONAME_SEARCH"; then |
# FIXME: I hate duplicating code | # FIXME: I hate duplicating code |
# Only build missing direct dependencies | # Only build missing direct dependencies |
MISSING_LIBS=$( | MISSING_LIBS=$( |
|
|
echo_v " broken $FILE (no version information available)" | echo_v " broken $FILE (no version information available)" |
done | done |
fi | fi |
echo -e " done.\n ($LIST.3_rebuild)" |
[[ -rs $LIST.3_rebuild ]] || clean_exit |
fi |
einfo "Generated new $LIST.3_rebuild" |
|
fi |
if [[ $PACKAGE_NAMES ]]; then |
} |
echo |
get_packages() { |
color_echo green -n 'Assigning files to packages...' |
einfo 'Assigning files to packages' |
if [[ -r $LIST.4_packages_raw ]]; then |
if [[ -rs $LIST.4_packages_raw ]]; then |
echo " using existing $LIST.4_packages_raw." |
einfo "Found existing $LIST.4_packages_raw" |
else | else |
set_trap "$LIST.4_packages*" | set_trap "$LIST.4_packages*" |
rm -f $LIST.4* | rm -f $LIST.4* |
|
|
if [[ $PORTAGE_UTILS ]]; then | if [[ $PORTAGE_UTILS ]]; then |
EXACT_PKG=$(qfile -qvC $FILE) | EXACT_PKG=$(qfile -qvC $FILE) |
elif [[ $PKGCORE ]]; then | elif [[ $PKGCORE ]]; then |
EXACT_PKG=$(pquery --nocolor --early-out --vdb --owns="$FILE") |
EXACT_PKG=$(pquery --nocolor --owns="$FILE") |
elif [[ $EQUERY ]]; then | elif [[ $EQUERY ]]; then |
EXACT_PKG=$(equery -q -C b $FILE) | EXACT_PKG=$(equery -q -C b $FILE) |
else | else |
|
|
PKG="${PKG%-*}" | PKG="${PKG%-*}" |
echo "$EXACT_PKG" >> $LIST.4_packages_raw | echo "$EXACT_PKG" >> $LIST.4_packages_raw |
echo "$FILE -> $EXACT_PKG" >> $LIST.4_package_owners | echo "$FILE -> $EXACT_PKG" >> $LIST.4_package_owners |
echo_v -n -e "\n $FILE -> $PKG" |
echo_v " $FILE -> $PKG" |
else | else |
color_echo -n -e "\n *** $FILE not owned by any package is broken! ***" |
ewarn " !!! $FILE not owned by any package is broken !!!" |
echo "$FILE -> (none)" >> $LIST.4_package_owners | echo "$FILE -> (none)" >> $LIST.4_package_owners |
echo_v -n -e "\n $FILE -> (none)" | echo_v -n -e "\n $FILE -> (none)" |
fi | fi |
done < "$LIST.3_rebuild" | done < "$LIST.3_rebuild" |
echo_v |
einfo "Generated new $LIST.4_packages_raw and $LIST.4_package_owners" |
echo -e " done.\n ($LIST.4_packages_raw, $LIST.4_package_owners)" |
|
fi | fi |
|
} |
echo |
clean_packages() { |
color_echo green -n "Cleaning list of packages to rebuild..." |
einfo 'Cleaning list of packages to rebuild' |
if [[ -f $LIST.4_packages ]]; then |
if [[ -rs $LIST.4_packages ]]; then |
echo " using existing $LIST.4_packages." |
einfo "Found existing $LIST.4_packages" |
else | else |
sort -u $LIST.4_packages_raw > $LIST.4_packages | sort -u $LIST.4_packages_raw > $LIST.4_packages |
echo -e " done.\n ($LIST.4_packages)" |
einfo "Generated new $LIST.4_packages" |
fi | fi |
|
} |
echo |
assign_packages_to_ebuilds() { |
color_echo green -n 'Assigning packages to ebuilds...' |
einfo 'Assigning packages to ebuilds' |
if [[ -f $LIST.4_ebuilds ]]; then |
if [[ -rs $LIST.4_ebuilds ]]; then |
echo " using existing $LIST.4_ebuilds." |
einfo "Found existing $LIST.4_ebuilds" |
else |
elif [[ -rs $LIST.4_packages ]]; then |
if [[ -s $LIST.4_packages ]]; then |
|
set_trap "$LIST.4_ebuilds" | set_trap "$LIST.4_ebuilds" |
while read EXACT_PKG; do | while read EXACT_PKG; do |
# Get the slot | # Get the slot |
|
|
SLOT=$(</var/db/pkg/$EXACT_PKG/SLOT) | SLOT=$(</var/db/pkg/$EXACT_PKG/SLOT) |
portageq best_visible $PORTAGE_ROOT $PKG:$SLOT | portageq best_visible $PORTAGE_ROOT $PKG:$SLOT |
done < "$LIST.4_packages" > "$LIST.4_ebuilds" | done < "$LIST.4_packages" > "$LIST.4_ebuilds" |
echo -e " done.\n ($LIST.4_ebuilds)" |
einfo "Generated new $LIST.4_ebuilds" |
else | else |
echo " Nothing to rebuild" |
einfo 'Nothing to rebuild.' |
rm "$LIST.4_ebuilds" |
die 1 '(The program should have already quit, so this is a minor bug.)' |
fi |
|
fi | fi |
else |
} |
echo |
get_exact_ebuilds() { |
color_echo green -n 'Assigning files to ebuilds...' |
einfo 'Assigning files to ebuilds' |
if [[ -r $LIST.4_ebuilds ]]; then |
if [[ -rs $LIST.4_ebuilds ]]; then |
echo " using existing $LIST.4_ebuilds." |
einfo "Found existing $LIST.4_ebuilds" |
else |
elif [[ -rs $LIST.3_rebuild ]]; then |
if [[ -s $LIST.3_rebuild ]]; then |
rebuildList=" $(<"$LIST.3_rebuild") " |
rebuildList=$(awk '{print $2}' "$LIST.3_rebuild") |
rebuildList=(${rebuildList//[[:space:]]obj[[:space:]]/ }) |
if [[ $PORTAGE_UTILS ]]; then | if [[ $PORTAGE_UTILS ]]; then |
qfile -qvC $rebuildList # Don't put quotes around $rebuildList |
qfile -qvC ${rebuildList[@]} |
# elif [[ $PKGCORE ]]; then |
elif [[ $PKGCORE ]]; then |
# This is really slow... |
IFS=, |
# pquery --nocolor --early-out --vdb --owns-re="(${rebuildList//[[:space:]]/|})" |
pquery --nocolor --owns="${rebuildList[*]}" |
# elif [[ $EQUERY ]]; then |
IFS="$oIFS" |
# equery can't seem to do this operation on multiple args at all |
elif [[ $EQUERY ]]; then |
|
equery -q -C b ${rebuildList[@]} |
else | else |
find /var/db/pkg -name CONTENTS | | find /var/db/pkg -name CONTENTS | |
xargs grep -Fl "$rebuildList" | | xargs grep -Fl "$rebuildList" | |
sed 's:/var/db/pkg/\(.*\)/CONTENTS:=\1:' | sed 's:/var/db/pkg/\(.*\)/CONTENTS:=\1:' |
fi > $LIST.4_ebuilds | fi > $LIST.4_ebuilds |
echo -e " done.\n ($LIST.4_ebuilds)" |
einfo "Generated new $LIST.4_ebuilds" |
else | else |
echo " Nothing to rebuild" |
einfo 'Nothing to rebuild.' |
rm > $LIST.4_ebuilds |
die 1 '(The program should have already quit, so this is a minor bug.)' |
fi | fi |
|
} |
|
get_build_order() { |
|
if [[ ! $order_packages ]]; then |
|
einfo 'Skipping package ordering' |
|
return |
fi | fi |
fi |
einfo 'Evaluating package order' |
|
if [[ -rs $LIST.5_order ]]; then |
# TODO: let the user skip this step |
einfo "Found existing $LIST.5_order" |
color_echo green -n $'\nEvaluating package order...' |
else |
if [[ -r $LIST.5_order ]]; then |
|
echo " using existing $LIST.5_order." |
|
else |
|
set_trap "$LIST.5_order" | set_trap "$LIST.5_order" |
RAW_REBUILD_LIST=$(<"$LIST.4_ebuilds") | RAW_REBUILD_LIST=$(<"$LIST.4_ebuilds") |
if [[ $RAW_REBUILD_LIST ]]; then | if [[ $RAW_REBUILD_LIST ]]; then |
OLD_EMERGE_DEFAULT_OPTS="$EMERGE_DEFAULT_OPTS" | OLD_EMERGE_DEFAULT_OPTS="$EMERGE_DEFAULT_OPTS" |
export EMERGE_DEFAULT_OPTS="--nospinner --pretend --oneshot --nodeps --quiet" | export EMERGE_DEFAULT_OPTS="--nospinner --pretend --oneshot --nodeps --quiet" |
RAW_REBUILD_LIST="=${RAW_REBUILD_LIST//[[:space:]]/ =}" | RAW_REBUILD_LIST="=${RAW_REBUILD_LIST//[[:space:]]/ =}" |
REBUILD_GREP=$(emerge $RAW_REBUILD_LIST | awk '{print $NF}') && |
REBUILD_GREP=$(emerge $RAW_REBUILD_LIST | sed 's/\[[^]]*\]//g') && |
emerge --deep $RAW_REBUILD_LIST | awk '{print $NF}' | |
emerge --deep $RAW_REBUILD_LIST | sed 's/\[[^]]*\]//g' | |
grep -F "$REBUILD_GREP" > $LIST.5_order || { | grep -F "$REBUILD_GREP" > $LIST.5_order || { |
set_color red |
eerror |
cat <<- EOF |
eerror 'Warning: Failed to resolve package order.' |
Warning: Failed to resolve package order. |
eerror 'Will merge in arbitrary order' |
Will merge in "random" order! |
eerror |
EOF |
|
set_color |
|
cat <<- EOF | cat <<- EOF |
Possible reasons: | Possible reasons: |
- An ebuild is no longer in the portage tree. | - An ebuild is no longer in the portage tree. |
|
|
echo -n -e '\a.' | echo -n -e '\a.' |
sleep 1 | sleep 1 |
done | done |
|
rm -f "$LIST.5_order" |
} | } |
export EMERGE_DEFAULT_OPTS="$OLD_EMERGE_DEFAULT_OPTS" | export EMERGE_DEFAULT_OPTS="$OLD_EMERGE_DEFAULT_OPTS" |
else | else |
rm -f "$LIST.5_order" |
einfo 'Nothing to rebuild.' |
|
die 1 '(The program should have already quit, so this is a minor bug.)' |
|
fi |
fi | fi |
[[ -f $LIST.5_order ]] && echo -e " done.\n ($LIST.5_order)" || |
[[ -rs $LIST.5_order ]] && einfo "Generated new $LIST.5_order" |
echo -e " done.\n ($LIST.4_ebuilds)" |
} |
|
|
|
get_search_env |
|
echo |
|
get_files |
|
echo |
|
get_ldpath |
|
echo |
|
main_checks |
|
echo |
|
if [[ $PACKAGE_NAMES ]]; then |
|
get_packages |
|
echo |
|
clean_packages |
|
echo |
|
assign_packages_to_ebuilds |
|
else |
|
get_exact_ebuilds |
fi | fi |
|
echo |
|
get_build_order |
|
echo |
| |
# Clean up no longer needed environment variables | # Clean up no longer needed environment variables |
unset COMPLETE_LD_LIBRARY_PATH SEARCH_DIRS SEARCH_DIRS_MASK LD_LIBRARY_MASK PORTAGE_ROOT CALLED_OPTIONS |
unset COMPLETE_LD_LIBRARY_PATH SEARCH_DIRS SEARCH_DIRS_MASK LD_LIBRARY_MASK \ |
|
PORTAGE_ROOT |
| |
[[ -f $LIST.5_order ]] && REBUILD_LIST=$(<"$LIST.5_order") || |
[[ -rs $LIST.5_order ]] && REBUILD_LIST=($(<"$LIST.5_order")) || |
REBUILD_LIST=$(<"$LIST.4_ebuilds") |
REBUILD_LIST=($(<"$LIST.4_ebuilds")) |
REBUILD_LIST="=${REBUILD_LIST//[[:space:]]/ =}" |
|
| |
trap - SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM | trap - SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM |
| |
if [[ ! $REBUILD_LIST ]]; then |
REBUILD_LIST="=${REBUILD_LIST[@]}" |
[[ $KEEPTEMP ]] || rm $LIST.?_* |
REBUILD_LIST="${REBUILD_LIST//[[:space:]]/ =}" |
set_color green |
|
die 0 $'\n'"$OK_TEXT... All done. " |
|
fi |
|
|
|
IS_REAL_MERGE=1 |
|
for option in $EMERGE_OPTIONS; do |
|
case $option in |
|
-p|--pretend|-f|--fetchonly) |
|
unset IS_REAL_MERGE |
|
break;; |
|
esac |
|
done |
|
|
|
echo |
|
color_echo green -e "All prepared. Starting rebuild..." |
|
| |
|
einfo 'All prepared. Starting rebuild' |
echo "emerge --oneshot $EMERGE_OPTIONS $REBUILD_LIST" | echo "emerge --oneshot $EMERGE_OPTIONS $REBUILD_LIST" |
| |
if [[ $IS_REAL_MERGE ]]; then |
if is_real_merge; then |
for i in {1..10}; do | for i in {1..10}; do |
echo -n -e '\a.' | echo -n -e '\a.' |
sleep 1 | sleep 1 |
|
|
exec 0<&6 6<&- | exec 0<&6 6<&- |
| |
if (( $(<"$LIST.6_status") != 0 )); then | if (( $(<"$LIST.6_status") != 0 )); then |
set_color red |
ewarn |
cat <<- EOF |
ewarn "$appname failed to emerge all packages." |
|
ewarn 'you have the following choices:' |
revdep-rebuild failed to emerge all packages. |
einfo "- If emerge failed during the build, fix the problems and re-run $appname." |
you have the following choices: |
einfo '- Use /etc/portage/package.keywords to unmask a newer version of the package.' |
|
einfo " (and remove $LIST.5_order to be evaluated again)" |
EOF |
einfo '- Modify the above emerge command and run it manually.' |
set_color |
einfo '- Compile or unmerge unsatisfied packages manually,' |
cat <<- EOF |
einfo ' remove temporary files, and try again.' |
- if emerge failed during the build, fix the problems and re-run revdep-rebuild |
einfo ' (you can edit package/ebuild list first)' |
or |
einfo |
- use -X or --package-names as first argument (trys to rebuild package, not exact |
einfo 'To remove temporary files, please run:' |
ebuild) |
einfo "rm $LIST*.?_*" |
or |
|
- set ACCEPT_KEYWORDS=\"~<your platform>\" and/or /etc/portage/package.unmask |
|
(and remove $LIST.5_order to be evaluated again) |
|
or |
|
- modify the above emerge command and run it manually |
|
or |
|
- compile or unmerge unsatisfied packages manually, remove temporary files and |
|
try again (you can edit package/ebuild list first) |
|
EOF |
|
color_echo green 'To remove temporary files, please run:' |
|
echo "rm $LIST*.?_*" |
|
exit $EMERGE_STATUS | exit $EMERGE_STATUS |
|
elif is_real_merge; then |
|
trap_cmd() { |
|
eerror "terminated. Please remove the temporary files manually:" |
|
eerror "rm $LIST*.?_*" |
|
exit 1 |
|
} |
|
trap trap_cmd SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM |
|
einfo 'Build finished correctly. Removing temporary files...' |
|
einfo |
|
einfo 'You can re-run revdep-rebuild to verify that all libraries and binaries' |
|
einfo 'are fixed. If some inconsistency remains, it can be orphaned file, deep' |
|
einfo 'dependency, binary package or specially evaluated library.' |
else | else |
if [[ $IS_REAL_MERGE ]]; then |
einfo 'Now you can remove -p (or --pretend) from arguments and re-run revdep-rebuild.' |
trap "echo -e \" terminated. Please remove them manually:\nrm $LIST*.?_*\" ; exit 1" \ |
|
SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM |
|
color_echo green "Build finished correctly. Removing temporary files..." |
|
cat <<- EOF |
|
You can re-run revdep-rebuild to verify that all libraries and binaries |
|
are fixed. If some inconsistency remains, it can be orphaned file, deep |
|
dependency, binary package or specially evaluated library. |
|
EOF |
|
else |
|
color_echo green 'Now you can remove -p (or --pretend) from arguments and re-run revdep-rebuild.' |
|
fi |
|
fi | fi |