View | Details | Raw Unified
Collapse All | Expand All

(-) revdep-rebuild.orig (-271 / +260 lines)
 Lines 1-20    Link Here 
#!/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:
#
#
 Lines 29-34    Link Here 
# 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.)'
 Lines 80-94    Link Here 
  -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).
 Lines 122-233    Link Here 
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)
 Lines 265-280    Link Here 
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")
 Lines 295-315    Link Here 
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>"
 Lines 326-409    Link Here 
	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"
 Lines 414-434    Link Here 
			$(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"))
 Lines 440-451    Link Here 
			# (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=$(
 Lines 515-528    Link Here 
			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*
 Lines 530-536    Link Here 
			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
 Lines 546-577    Link Here 
				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
 Lines 580-639    Link Here 
				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.
 Lines 644-688    Link Here 
					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
 Lines 704-745    Link Here 
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