From: fuzzyray Date: Thu, 5 Jul 2007 20:43:31 +0000 (-0000) Subject: Added refactored revdep-rebuild from Michael A. Smith (Bug #184042) X-Git-Tag: gentoolkit-0.2.4.3~102 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=11b137ccda17d8bf598fd5d0d6f3c93a7f2d03d6;p=gentoolkit.git Added refactored revdep-rebuild from Michael A. Smith (Bug #184042) svn path=/; revision=411 --- diff --git a/trunk/ChangeLog b/trunk/ChangeLog index 0364285..c687f83 100644 --- a/trunk/ChangeLog +++ b/trunk/ChangeLog @@ -1,3 +1,7 @@ +2007-07-05: Paul Varner + * revdep-rebuild: Added refactored revdep-rebuild from Michael A. + Smith (Bug #184042) + 2007-05-30: Marius Mauch * glsa-check: check SLOT when selecting and displaying upgrades * glsa-check: new --emergelike option to use the best version diff --git a/trunk/src/revdep-rebuild/Makefile b/trunk/src/revdep-rebuild/Makefile index 934872f..59c97c7 100644 --- a/trunk/src/revdep-rebuild/Makefile +++ b/trunk/src/revdep-rebuild/Makefile @@ -11,13 +11,14 @@ all: dist: mkdir -p ../../$(distdir)/src/revdep-rebuild - cp Makefile AUTHORS README TODO ChangeLog revdep-rebuild revdep-rebuild.1 find_pkgs.py 99revdep-rebuild ../../$(distdir)/src/revdep-rebuild/ + cp Makefile AUTHORS README TODO ChangeLog revdep-rebuild revdep-rebuild.1 revdep-rebuild-rewrite find_pkgs.py 99revdep-rebuild ../../$(distdir)/src/revdep-rebuild/ install: - install -m 0755 revdep-rebuild $(bindir)/ + install -m 0755 revdep-rebuild-rewrite $(bindir)/revdep-rebuild install -d $(DESTDIR)/usr/lib/gentoolkit/bin/ install -m 0755 find_pkgs.py $(DESTDIR)/usr/lib/gentoolkit/bin/ + install -m 0755 revdep-rebuild $(DESTDIR)/usr/lib/gentoolkit/bin/ install -d $(docdir)/revdep-rebuild install -m 0644 AUTHORS README TODO $(docdir)/revdep-rebuild/ install -m 0644 revdep-rebuild.1 $(mandir)/ diff --git a/trunk/src/revdep-rebuild/revdep-rebuild-1 b/trunk/src/revdep-rebuild/revdep-rebuild-1 deleted file mode 100755 index a33d024..0000000 --- a/trunk/src/revdep-rebuild/revdep-rebuild-1 +++ /dev/null @@ -1,351 +0,0 @@ -#! /bin/bash - -# Copyright 1999-2003 Gentoo Technologies, Inc. -# $Header$ - -# revdep-rebuild: Reverse dependency rebuilder. -# Author: Stanislav Brabec - -# requires: qpkg - -# Known problems: -# -# In exact ebuild mode revdep-rebuild can fails to get order packages, -# which are not up to date. This is because emerge first tries to -# merge latest package and last in resort it tries to degrade. -# http://bugs.gentoo.org/show_bug.cgi?id=23018 -# -# Rebuild in --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 - -# Mask of specially evaluated libraries (exactly one space separated). -LD_LIBRARY_MASK="libodbcinst.so libodbc.so libjava.so libjvm.so" - -# List of directories to be searched (feel free to edit it) -# Note /usr/libexec and /usr/local/subprefix cotradicts FHS, but are present -# /var/something is for cgi and similar scripts -SEARCH_DIRS="/lib /bin /sbin /usr/lib /usr/bin /usr/sbin /usr/libexec /usr/X11R6/lib /usr/X11R6/bin /usr/X11R6/sbin /usr/e1* /usr/local /usr/qt* /usr/kde/*/lib /usr/*-*-linux-gnu /opt /var/qmail /var/vpopmail /home/httpd/cgi-bin" - -# Base of temporary files names. -LIST=~/.revdep-rebuild - -shopt -s nullglob -shopt -s expand_aliases -unalias -a - -NO="\x1b[0;0m" -BR="\x1b[0;01m" -CY="\x1b[36;01m" -GR="\x1b[32;01m" -RD="\x1b[31;01m" -YL="\x1b[33;01m" -BL="\x1b[34;01m" - -alias echo_v=echo - -PACKAGE_NAMES=false -SONAME="not found" -SONAME_GREP=fgrep -SEARCH_BROKEN=true - -while : ; do - case "$1" in - -h | --help ) - echo "Usage: $0 [OPTIONS] [--] [EMERGE_OPTIONS]" - echo - echo "Broken reverse dependency rebuilder." - echo - echo " -X, --package-names recompile based on package names, not exact versions" - echo " --soname SONAME recompile packages using library with SONAME instead" - echo " of broken library" - echo " --soname-regexp SONAME" - echo " the same as --soname, but accepts grep-style regexp" - echo " -q, --quiet be less verbose" - echo - echo "Calls emerge, all other options are used for it (e. g. -p, --pretend)." - echo - echo "Report bugs to " - exit 0 - ;; - -X | --package-names ) - PACKAGE_NAMES=true - shift - ;; - -q | --quiet ) - alias echo_v=: - shift - ;; - --soname=* ) - SONAME="${1#*=}" - SEARCH_BROKEN=false - shift - ;; - --soname ) - SONAME="$2" - SEARCH_BROKEN=false - shift 2 - ;; - --soname-regexp=* ) - SONAME="${1#*=}" - SONAME_GREP=grep - SEARCH_BROKEN=false - shift - ;; - --soname-regexp ) - SONAME="$2" - SONAME_GREP=grep - SEARCH_BROKEN=false - shift 2 - ;; - -- ) - shift - break - ;; - * ) - break - ;; - esac -done - -function set_trap () { - trap "rm_temp $1" SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM -} - -function rm_temp () { - echo " terminated." - echo "Removing incomplete $1." - rm $1 - echo - exit 1 -} - -if $SEARCH_BROKEN ; then - SONAME_SEARCH="$SONAME" - LLIST=$LIST - HEAD_TEXT="broken by any package update" - OK_TEXT="Dynamic linking on your system is consistent" - WORKING_TEXT=" consistency" -else - SONAME_SEARCH=" $SONAME " - LLIST=${LIST}_$(echo "$SONAME_SEARCH$SONAME" | md5sum | head -c 8) - HEAD_TEXT="using given shared object name" - OK_TEXT="There are no dynamic links to $SONAME" - WORKING_TEXT="" -fi - -echo -echo "Checking reverse dependencies..." -echo "Packages containing binaries and libraries $HEAD_TEXT," -echo "will be recompiled." - -echo -echo -n -e "${GR}Collecting system binaries and libraries...${NO}" -if [ -f $LIST.1_files ] ; then - echo " using existing $LIST.1_files." -else - set_trap "$LIST.1_files" - find $SEARCH_DIRS -type f \( -perm +u+x -o -name '*.so' -o -name '*.so.*' \) 2>/dev/null >$LIST.1_files - echo -e " done.\n ($LIST.1_files)" -fi - -if $SEARCH_BROKEN ; then - echo - echo -n -e "${GR}Collecting complete LD_LIBRARY_PATH...${NO}" - if [ -f $LIST.2_ldpath ] ; then - echo " using existing $LIST.2_ldpath." - else - set_trap "$LIST.2_ldpath" - ( - grep '.*\.so\(\|\..*\)$' <$LIST.1_files | sed 's:/[^/]*$::' - sed '/^#/d;s/#.*$//' $LIST.2_ldpath - echo -e " done.\n ($LIST.2_ldpath)" - fi - export COMPLETE_LD_LIBRARY_PATH="$(cat $LIST.2_ldpath)" -fi - -echo -echo -n -e "${GR}Checking dynamic linking$WORKING_TEXT...${NO}" -if [ -f $LLIST.3_rebuild ] ; then - echo " using existing $LLIST.3_rebuild." -else - echo_v - set_trap "$LLIST.3_rebuild" - LD_MASK="\\( $(echo "$LD_LIBRARY_MASK" | sed 's/\./\\./g;s/ / \\| /g') \\)" - echo -n >$LLIST.3_rebuild - cat $LIST.1_files | while read FILE ; do -# Note: double checking seems to be faster than single -# with complete path (special add ons are rare). - if ldd "$FILE" 2>/dev/null | grep -v "$LD_MASK" | - $SONAME_GREP -q "$SONAME_SEARCH" ; then - if $SEARCH_BROKEN ; then - if LD_LIBRARY_PATH="$COMPLETE_LD_LIBRARY_PATH" \ - ldd "$FILE" 2>/dev/null | grep -v "$LD_MASK" | - $SONAME_GREP -q "$SONAME_SEARCH" ; then - echo "$FILE" >>$LLIST.3_rebuild - echo_v " broken $FILE (requires $(ldd "$FILE" | sed -n 's/ \(.*\) => not found$/\1/p' | tr '\n' ' ' | sed 's/ $//' ))" - fi - else - echo "$FILE" >>$LLIST.3_rebuild - echo_v " found $FILE" - fi - fi - done - echo -e " done.\n ($LLIST.3_rebuild)" -fi - -if $PACKAGE_NAMES ; then - EXACT_EBUILDS=false - - echo - echo -n -e "${GR}Assigning files to packages...${NO}" - if [ -f $LLIST.4_packages_raw ] ; then - echo " using existing $LLIST.4_packages_raw." - else - set_trap "$LLIST.4_packages_raw" - echo -n >$LLIST.4_packages_raw - echo -n >$LLIST.4_package_owners - cat $LLIST.3_rebuild | while read FILE ; do - PKG="$(qpkg -nc -f "$FILE")" - if [ -z "$PKG" ] ; then - echo -n -e "\n ${RD}*** $FILE not owned by any package is broken! ***${NO}" - echo "$FILE -> (none)" >> $LLIST.4_package_owners - echo_v -n -e "\n $FILE -> (none)" - else - echo "$PKG" >> $LLIST.4_packages_raw - echo "$FILE -> $PKG" >> $LLIST.4_package_owners - echo_v -n -e "\n $FILE -> $PKG" - fi - done - echo_v - echo -e " done.\n ($LLIST.4_packages_raw, $LLIST.4_package_owners)" - fi - - echo - echo -n -e "${GR}Cleaning list of packages to rebuild...${NO}" - if [ -f $LLIST.5_packages ] ; then - echo " using existing $LLIST.5_packages." - else - set_trap "$LLIST.5_packages" - sort <$LLIST.4_packages_raw | uniq >$LLIST.5_packages - echo -e " done.\n ($LLIST.5_packages)" - fi - - RAW_REBUILD_LIST="$(cat $LLIST.5_packages | tr '\n' ' ')" - -else - EXACT_EBUILDS=true - - echo - echo -n -e "${GR}Assigning files to ebuilds...${NO}" - if [ -f $LLIST.4_ebuilds ] ; then - echo " using existing $LLIST.4_ebuilds." - else - set_trap "$LLIST.4_ebuilds" - cat $LLIST.3_rebuild | sed 's/^/obj /;s/$/ /' | - ( - cd /var/db/pkg - fgrep -l -f - */*/CONTENTS - ) | sed s:/CONTENTS:: > $LLIST.4_ebuilds - echo -e " done.\n ($LLIST.4_ebuilds)" - fi - - RAW_REBUILD_LIST="$(cat $LLIST.4_ebuilds | sed s/^/=/ | tr '\n' ' ')" -fi - -echo -echo -n -e "${GR}Evaluating package order...${NO}" -if [ -f $LLIST.5_order ] ; then - echo " using existing $LLIST.5_order." -else - if [ ! -z "$RAW_REBUILD_LIST" ] ; then - REBUILD_GREP="^\\($(emerge --nospinner --pretend --oneshot --nodeps $RAW_REBUILD_LIST | sed -n 's/\./\\&/g;s/ //g;s/$/\\/;s/^.*\]//p' | tr '\n' '|' | sed 's/|$//'))\$" - emerge --nospinner --pretend --oneshot --emptytree $RAW_REBUILD_LIST | sed -n 's/ //g;s/^.*\]//p' | grep "$REBUILD_GREP" >$LLIST.5_order - else - echo -n "" >$LLIST.5_order - fi - echo -e " done.\n ($LLIST.5_order)" -fi - -REBUILD_LIST="$(cat $LLIST.5_order | sed s/^/=/ | tr '\n' ' ')" - -trap - SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM - -if [ -z "$REBUILD_LIST" ] ; then - echo -e "\n${GR}$OK_TEXT... All done.${NO} " - rm $LIST.[1-2]_* - rm $LLIST.[3-9]_* - exit 0 -fi - -IS_REAL_MERGE=true -echo " $* " | grep -q '\( -p \| --pretend \)' && IS_REAL_MERGE=false - -echo -echo -e "${GR}All prepared. Starting rebuild...${NO}" -echo "emerge --oneshot --nodeps $@ $REBUILD_LIST" -if $IS_REAL_MERGE ; then - for i in . . . . . . . . . . ; do - echo -n -e '\a.' - sleep 1 - done - echo -fi - -#if $EXACT_EBUILDS ; then -# Uncomment following, if you want to recompile masked ebuilds. -## FIXME: Check for PORTDIR_OVERLAY -# echo -e "${GR}Temporarilly disablink package mask...${NO}" -# trap "mv -i /usr/portage/profiles/package.mask.hidden /usr/portage/profiles/package.mask ; echo -e "\\n\\nTerminated." ; exit 1" \ -# SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM -# mv -i /usr/portage/profiles/package.mask /usr/portage/profiles/package.mask.hidden -#fi - -# Run in background to correctly handle Ctrl-C -( - emerge --oneshot --nodeps $@ $REBUILD_LIST - echo $? >$LLIST.6_status -) & -wait - -#if $EXACT_EBUILDS ; then -# mv -i /usr/portage/profiles/package.mask.hidden /usr/portage/profiles/package.mask -# trap - SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM -#fi - -if [ "$(cat $LLIST.6_status)" -gt 0 ] ; then - echo - echo -e "${RD}Result is not OK, you have following chances:${NO}" - echo "- if emerge failed during build, fix the problems and re-run revdep-rebuild" - echo " or" - echo "- use -X or --package-names as first argument (try to rebuild package, not exact" - echo " ebuild - ignores SLOT!)" - echo " or" - echo "- modify the above emerge command and run it manually" - echo " or" - echo "- compile or unmerge unsatisfied packages manually, remove temporary files and" - echo " try again (you can edit package/ebuild list first)" - echo - echo -e "${GR}To remove temporary files, please run:${NO}" - echo "rm $LIST*.?_*" -else - if $IS_REAL_MERGE ; then - trap "echo -e \" terminated. Please remove them manually:\nrm $LIST*.?_*\" ; exit 1" \ - SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM - echo -n -e "${GR}Build finished correctly. Removing temporary files...${NO} " - for i in . . . . . . . . . . ; do - echo -n -e '.' - sleep 1 - done - echo - rm $LIST.[1-2]_* - rm $LLIST.[3-9]_* - echo "You can re-run revdep-rebuild to verify that all libraries and binaries" - echo "are fixed. If some inconsistency remains, it can be orphaned file, deep" - echo "dependency, binary package or specially evaluated library." - else - echo -e "${GR}Now you can remove -p (or --pretend) from arguments and re-run revdep-rebuild.${NO}" - fi -fi diff --git a/trunk/src/revdep-rebuild/revdep-rebuild-2 b/trunk/src/revdep-rebuild/revdep-rebuild-2 deleted file mode 100755 index 0eb326f..0000000 --- a/trunk/src/revdep-rebuild/revdep-rebuild-2 +++ /dev/null @@ -1,369 +0,0 @@ -#! /bin/bash - -# Copyright 1999-2003 Gentoo Technologies, Inc. -# $Header$ - -# revdep-rebuild: Reverse dependency rebuilder. -# Author: Stanislav Brabec - -# requires: qpkg - -# Known problems: -# -# In exact ebuild mode revdep-rebuild can fails to get order packages, -# which are not up to date. This is because emerge first tries to -# merge latest package and last in resort it tries to degrade. -# http://bugs.gentoo.org/show_bug.cgi?id=23018 -# -# Rebuild in --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 - -# Mask of specially evaluated libraries (exactly one space separated). -LD_LIBRARY_MASK="libodbcinst.so libodbc.so libjava.so libjvm.so" - -# List of directories to be searched (feel free to edit it) -# Note /usr/libexec and /usr/local/subprefix cotradicts FHS, but are present -# /var/something is for cgi and similar scripts -SEARCH_DIRS="/lib /bin /sbin /usr/lib /usr/bin /usr/sbin /usr/libexec /usr/X11R6/lib /usr/X11R6/bin /usr/X11R6/sbin /usr/e1* /usr/local /usr/qt* /usr/kde/*/lib /usr/*-*-linux-gnu /opt /var/qmail /var/vpopmail /home/httpd/cgi-bin" - -# Base of temporary files names. -LIST=~/.revdep-rebuild - -shopt -s nullglob -shopt -s expand_aliases -unalias -a - -NO="\x1b[0;0m" -BR="\x1b[0;01m" -CY="\x1b[36;01m" -GR="\x1b[32;01m" -RD="\x1b[31;01m" -YL="\x1b[33;01m" -BL="\x1b[34;01m" - -alias echo_v=echo - -PACKAGE_NAMES=false -SONAME="not found" -SONAME_GREP=fgrep -SEARCH_BROKEN=true - -while : ; do - case "$1" in - -h | --help ) - echo "Usage: $0 [OPTIONS] [--] [EMERGE_OPTIONS]" - echo - echo "Broken reverse dependency rebuilder." - echo - echo " -X, --package-names recompile based on package names, not exact versions" - echo " --soname SONAME recompile packages using library with SONAME instead" - echo " of broken library" - echo " --soname-regexp SONAME" - echo " the same as --soname, but accepts grep-style regexp" - echo " -q, --quiet be less verbose" - echo - echo "Calls emerge, all other options are used for it (e. g. -p, --pretend)." - echo - echo "Report bugs to " - exit 0 - ;; - -X | --package-names ) - PACKAGE_NAMES=true - shift - ;; - -q | --quiet ) - alias echo_v=: - shift - ;; - --soname=* ) - SONAME="${1#*=}" - SEARCH_BROKEN=false - shift - ;; - --soname ) - SONAME="$2" - SEARCH_BROKEN=false - shift 2 - ;; - --soname-regexp=* ) - SONAME="${1#*=}" - SONAME_GREP=grep - SEARCH_BROKEN=false - shift - ;; - --soname-regexp ) - SONAME="$2" - SONAME_GREP=grep - SEARCH_BROKEN=false - shift 2 - ;; - -- ) - shift - break - ;; - * ) - break - ;; - esac -done - -function set_trap () { - trap "rm_temp $1" SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM -} - -function rm_temp () { - echo " terminated." - echo "Removing incomplete $1." - rm $1 - echo - exit 1 -} - -if $SEARCH_BROKEN ; then - SONAME_SEARCH="$SONAME" - LLIST=$LIST - HEAD_TEXT="broken by any package update" - OK_TEXT="Dynamic linking on your system is consistent" - WORKING_TEXT=" consistency" -else - SONAME_SEARCH=" $SONAME " - LLIST=${LIST}_$(echo "$SONAME_SEARCH$SONAME" | md5sum | head -c 8) - HEAD_TEXT="using given shared object name" - OK_TEXT="There are no dynamic links to $SONAME" - WORKING_TEXT="" -fi - -echo -echo "Checking reverse dependencies..." -echo "Packages containing binaries and libraries $HEAD_TEXT," -echo "will be recompiled." - -echo -echo -n -e "${GR}Collecting system binaries and libraries...${NO}" -if [ -f $LIST.1_files ] ; then - echo " using existing $LIST.1_files." -else - set_trap "$LIST.1_files" - find $SEARCH_DIRS -type f \( -perm +u+x -o -name '*.so' -o -name '*.so.*' \) 2>/dev/null >$LIST.1_files - echo -e " done.\n ($LIST.1_files)" -fi - -if $SEARCH_BROKEN ; then - echo - echo -n -e "${GR}Collecting complete LD_LIBRARY_PATH...${NO}" - if [ -f $LIST.2_ldpath ] ; then - echo " using existing $LIST.2_ldpath." - else - set_trap "$LIST.2_ldpath" - ( - grep '.*\.so\(\|\..*\)$' <$LIST.1_files | sed 's:/[^/]*$::' - sed '/^#/d;s/#.*$//' $LIST.2_ldpath - echo -e " done.\n ($LIST.2_ldpath)" - fi - export COMPLETE_LD_LIBRARY_PATH="$(cat $LIST.2_ldpath)" -fi - -echo -echo -n -e "${GR}Checking dynamic linking$WORKING_TEXT...${NO}" -if [ -f $LLIST.3_rebuild ] ; then - echo " using existing $LLIST.3_rebuild." -else - echo_v - set_trap "$LLIST.3_rebuild" - LD_MASK="\\( $(echo "$LD_LIBRARY_MASK" | sed 's/\./\\./g;s/ / \\| /g') \\)" - echo -n >$LLIST.3_rebuild - cat $LIST.1_files | while read FILE ; do -# Note: double checking seems to be faster than single -# with complete path (special add ons are rare). - if ldd "$FILE" 2>/dev/null | grep -v "$LD_MASK" | - $SONAME_GREP -q "$SONAME_SEARCH" ; then - if $SEARCH_BROKEN ; then - if LD_LIBRARY_PATH="$COMPLETE_LD_LIBRARY_PATH" \ - ldd "$FILE" 2>/dev/null | grep -v "$LD_MASK" | - $SONAME_GREP -q "$SONAME_SEARCH" ; then - echo "$FILE" >>$LLIST.3_rebuild - echo_v " broken $FILE (requires $(ldd "$FILE" | sed -n 's/ \(.*\) => not found$/\1/p' | tr '\n' ' ' | sed 's/ $//' ))" - fi - else - echo "$FILE" >>$LLIST.3_rebuild - echo_v " found $FILE" - fi - fi - done - echo -e " done.\n ($LLIST.3_rebuild)" -fi - -if $PACKAGE_NAMES ; then - EXACT_EBUILDS=false - - echo - echo -n -e "${GR}Assigning files to packages...${NO}" - if [ -f $LLIST.4_packages_raw ] ; then - echo " using existing $LLIST.4_packages_raw." - else - set_trap "$LLIST.4_packages_raw" - echo -n >$LLIST.4_packages_raw - echo -n >$LLIST.4_package_owners - cat $LLIST.3_rebuild | while read FILE ; do - PKG="$(qpkg -nc -f "$FILE")" - if [ -z "$PKG" ] ; then - echo -n -e "\n ${RD}*** $FILE not owned by any package is broken! ***${NO}" - echo "$FILE -> (none)" >> $LLIST.4_package_owners - echo_v -n -e "\n $FILE -> (none)" - else - echo "$PKG" >> $LLIST.4_packages_raw - echo "$FILE -> $PKG" >> $LLIST.4_package_owners - echo_v -n -e "\n $FILE -> $PKG" - fi - done - echo_v - echo -e " done.\n ($LLIST.4_packages_raw, $LLIST.4_package_owners)" - fi - - echo - echo -n -e "${GR}Cleaning list of packages to rebuild...${NO}" - if [ -f $LLIST.5_packages ] ; then - echo " using existing $LLIST.5_packages." - else - set_trap "$LLIST.5_packages" - sort <$LLIST.4_packages_raw | uniq >$LLIST.5_packages - echo -e " done.\n ($LLIST.5_packages)" - fi - - RAW_REBUILD_LIST="$(cat $LLIST.5_packages | tr '\n' ' ')" - -else - EXACT_EBUILDS=true - - echo - echo -n -e "${GR}Assigning files to ebuilds...${NO}" - if [ -f $LLIST.4_ebuilds ] ; then - echo " using existing $LLIST.4_ebuilds." - else - set_trap "$LLIST.4_ebuilds" - cat $LLIST.3_rebuild | sed 's/^/obj /;s/$/ /' | - ( - cd /var/db/pkg - fgrep -l -f - */*/CONTENTS - ) | sed s:/CONTENTS:: > $LLIST.4_ebuilds - echo -e " done.\n ($LLIST.4_ebuilds)" - fi - - RAW_REBUILD_LIST="$(cat $LLIST.4_ebuilds | sed s/^/=/ | tr '\n' ' ')" -fi - -echo -echo -n -e "${GR}Evaluating package order...${NO}" -if [ -f $LLIST.5_order ] ; then - echo " using existing $LLIST.5_order." -else - if [ ! -z "$RAW_REBUILD_LIST" ] ; then - REBUILD_GREP="^\\($( (emerge --nospinner --pretend --oneshot --nodeps $RAW_REBUILD_LIST ; echo $? >$LLIST.5_status ) | sed -n 's/\./\\&/g;s/ //g;s/$/\\/;s/\[[^]]*\]//gp' | tr '\n' '|' | sed 's/|$//'))\$" - if [ $(cat $LLIST.5_status) -gt 0 ] ; then - echo "" - echo -e "${RD}Warning: Failed to resolve package order." - echo -e "Will merge in \"random\" order!${NO}" - echo "Possible reasons:" - echo "- Some ebuilds are no more in portage tree." - echo "- Some ebuilds are masked, try to change ACCEPT_KEYWORDS=\"~\"" - echo " and/or use /etc/portage/package.unmask" - for i in . . . . . ; do - echo -n -e '\a.' - sleep 1 - done - ln -f $LLIST.4_ebuilds $LLIST.5_order - else - emerge --nospinner --pretend --oneshot --emptytree $RAW_REBUILD_LIST | sed -n 's/ //g;s/^.*\]//p' | grep "$REBUILD_GREP" >$LLIST.5_order - fi - else - echo -n "" >$LLIST.5_order - fi - echo -e " done.\n ($LLIST.5_order)" -fi - -REBUILD_LIST="$(cat $LLIST.5_order | sed s/^/=/ | tr '\n' ' ')" - -trap - SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM - -if [ -z "$REBUILD_LIST" ] ; then - echo -e "\n${GR}$OK_TEXT... All done.${NO} " - rm $LIST.[1-2]_* - rm $LLIST.[3-9]_* - exit 0 -fi - -IS_REAL_MERGE=true -echo " $* " | grep -q '\( -p \| --pretend \)' && IS_REAL_MERGE=false - -echo -echo -e "${GR}All prepared. Starting rebuild...${NO}" -echo "emerge --oneshot --nodeps $@ $REBUILD_LIST" -if $IS_REAL_MERGE ; then - for i in . . . . . . . . . . ; do - echo -n -e '\a.' - sleep 1 - done - echo -fi - -#if $EXACT_EBUILDS ; then -# Uncomment following, if you want to recompile masked ebuilds. -## FIXME: Check for PORTDIR_OVERLAY -# echo -e "${GR}Temporarilly disablink package mask...${NO}" -# trap "mv -i /usr/portage/profiles/package.mask.hidden /usr/portage/profiles/package.mask ; echo -e "\\n\\nTerminated." ; exit 1" \ -# SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM -# mv -i /usr/portage/profiles/package.mask /usr/portage/profiles/package.mask.hidden -#fi - -# Run in background to correctly handle Ctrl-C -( - emerge --oneshot --nodeps $@ $REBUILD_LIST - echo $? >$LLIST.6_status -) & -wait - -#if $EXACT_EBUILDS ; then -# mv -i /usr/portage/profiles/package.mask.hidden /usr/portage/profiles/package.mask -# trap - SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM -#fi - -if [ "$(cat $LLIST.6_status)" -gt 0 ] ; then - echo - echo -e "${RD}Result is not OK, you have following chances:${NO}" - echo "- if emerge failed during build, fix the problems and re-run revdep-rebuild" - echo " or" - echo "- use -X or --package-names as first argument (try to rebuild package, not exact" - echo " ebuild - ignores SLOT!)" - echo " or" - echo "- set ACCEPT_KEYWORDS=\"~\" and/or /etc/portage/package.unmask" - echo " (and remove $LLIST.5_order to be evaluated again)" - echo " or" - echo "- modify the above emerge command and run it manually" - echo " or" - echo "- compile or unmerge unsatisfied packages manually, remove temporary files and" - echo " try again (you can edit package/ebuild list first)" - echo - echo -e "${GR}To remove temporary files, please run:${NO}" - echo "rm $LIST*.?_*" -else - if $IS_REAL_MERGE ; then - trap "echo -e \" terminated. Please remove them manually:\nrm $LIST*.?_*\" ; exit 1" \ - SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM - echo -n -e "${GR}Build finished correctly. Removing temporary files...${NO} " - for i in . . . . . . . . . . ; do - echo -n -e '.' - sleep 1 - done - echo - rm $LIST.[1-2]_* - rm $LLIST.[3-9]_* - echo "You can re-run revdep-rebuild to verify that all libraries and binaries" - echo "are fixed. If some inconsistency remains, it can be orphaned file, deep" - echo "dependency, binary package or specially evaluated library." - else - echo -e "${GR}Now you can remove -p (or --pretend) from arguments and re-run revdep-rebuild.${NO}" - fi -fi diff --git a/trunk/src/revdep-rebuild/revdep-rebuild-rewrite b/trunk/src/revdep-rebuild/revdep-rebuild-rewrite new file mode 100755 index 0000000..068e348 --- /dev/null +++ b/trunk/src/revdep-rebuild/revdep-rebuild-rewrite @@ -0,0 +1,788 @@ +#!/bin/bash +# Copyright 1999-2007 Gentoo Foundation + +# revdep-rebuild: Reverse dependency rebuilder. +# Original Author: Stanislav Brabec +# Current Maintainer: Paul Varner + +# Known problems: +# +# In exact ebuild mode revdep-rebuild can fail to properly order packages, +# 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: +# +# LD_LIBRARY_MASK - Mask of specially evaluated libraries +# SEARCH_DIRS - List of directories to search for executables and libraries +# SEARCH_DIRS_MASK - List of directories to not search +# +# These variables can be prepended to either by setting the variable in +# your environment prior to execution, or by placing an entry in +# /etc/make.conf. +# +# An entry of "-*" means to clear the variable from that point forward. +# Example: env SEARCH_DIRS="/usr/bin -*" revdep-rebuild will set SEARCH_DIRS +# to contain only /usr/bin + +# Print pre-release disclaimer to stderr +cat 1>&2 << EOF + +WARNING +WARNING *** This is a rewritten version of revdep-rebuild *** +WARNING +WARNING +WARNING Please report any bugs to http://bugs.gentoo.org +WARNING +WARNING In the bug report please include the following information: +WARNING emerge --info +WARNING A copy of the output from the revdep-rebuild command +WARNING A copy of the .revdep-rebuild* files as an attachment +WARNING +WARNING If the bug is severe, the previous version of revdep-rebuild is located +WARNING at: /usr/lib/gentoolkit/bin/revdep-rebuild +WARNING +WARNING +WARNING *** This is a rewritten version of revdep-rebuild *** +WARNING + +EOF +sleep 2 + +rm() { + [[ $LIST && $appname ]] || + die 1 '$LIST or $appname is not defined! (This is a bug.)' + for i in $@; do + [[ $i = -* || $i = *.$appname* ]] || + die 1 "Oops, I'm not allowed to delete that. ($@)" + done + command rm "$@" +} +# Somewhat more portable find -executable +# FIXME/UNTESTED (I don't have access to all of the different versions of +# find.) +# Usage: find PATH ARGS -- use find like normal, except use -executable instead +# of various versions of -perm /+ blah blah and hacks +find() { + hash find || { die 1 'find not found!'; } + # We can be pretty sure "$0" should be executable. + if [[ $(command find "$0" -executable 2> /dev/null) ]]; then + unset -f find # We can just use the command find + elif [[ $(command find "$0" -perm /u+x 2> /dev/null) ]]; then + find() { + a=(${@//-executable/-perm \/u+x}) + a=(${a//-writable/-perm \/u+w}) + a=(${a//-readable/-perm \/r+w}) + command find "${a[@]}" + } + elif [[ $(command find "$0" -perm +u+x 2> /dev/null) ]]; then + find() { + a=(${@//-executable/-perm +u+x}) + a=(${a//-writable/-perm +u+w}) + a=(${a//-readable/-perm +r+w}) + command find "${a[@]}" + } + else # Last resort + find() { + a=(${@//-executable/-exec test -x '{}' \;}) + a=(${a//-writable/-exec test -w '{}' \;}) + a=(${a//-readable/-exec test -r '{}' \;}) + command find "${a[@]}" + } + fi + find "$@" +} +print_usage() { +cat << EOF +Usage: $0 [OPTIONS] [--] [EMERGE_OPTIONS] + +Broken reverse dependency rebuilder. + + -h, --help Print this usage + -k, --keep-temp Do not delete temporary files on exit + -e, --exact Emerge based on exact package version + -l, --no-ld-path Do not set LD_LIBRARY_PATH + -C, --nocolor Turn off colored output + -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) + -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). + +Report bugs to +EOF +} +# Usage: progress i n +# i: current item +# n: total number of items to process +progress() { + if [[ $quiet ]]; then + progress() { :; } + else + progress() { + echo -ne '\r \r' + echo -n "[ $(( $1 * 100 / $2 ))% ] " + } + progress $@ + fi +} +# Replace whitespace with linebreaks, normalize repeated '/' chars, and sort -u +# (If any libs have whitespace in their filenames, someone needs punishment.) +clean_var() { + local a=$(echo ${@%%-\**}) # Deliberately unquoted + # A benchmark shows this loop is faster than piping to sed, + # as long as there aren't more than a handful of '/' chars. + while [[ $a = *//* ]]; do a="${a//\/\///}"; done + sort -u <<< "${a// /$'\n'}" +} +# Exit and optionally output to sterr +die() { + local status=$1 + shift + echo "$@" >&2 + exit $status +} +# What to do when dynamic linking is consistent +clean_exit() { + [[ $KEEP_TEMP ]] || rm $LIST.?_* + set_color green + die 0 $'\n'"$OK_TEXT... All done. " +} +# Set the output color +set_color() { + # sets itself the first time it's called, so we don't have to check $NOCOLOR + # each time + if [[ $NOCOLOR ]]; then + 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() { + appname="${0##*/}" + echo_v() { echo "$@"; } + unset VERBOSE KEEP_TEMP EMERGE_OPTIONS remove_old_tempfiles + order_packages=1 + PACKAGE_NAMES=1 + SONAME="not found" + SEARCH_BROKEN=1 + FULL_LD_PATH=1 + local avoid_utils + while [[ $1 ]]; do + case $1 in + -h|--help) + print_usage + exit 0 + ;; + -e|--exact) + unset PACKAGE_NAMES + ;; + -o|--no-order) + unset order_packages + ;; + -q|--quiet) + echo_v() { : ; } + quiet=1 + EMERGE_OPTIONS+=" $1" + ;; + -L=*|--library=*|--soname=*|--soname-regexp=*) + SONAME="${1#*=}" + unset SEARCH_BROKEN + ;; + -L|--library|--soname|--soname-regexp) + [[ ! $2 || $2 = -* ]] && die 1 "Missing expected argument to $1" + shift + SONAME="$1" + unset SEARCH_BROKEN + ;; + -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) + export NOCOLOR=1 + ;; + -l|-np|--no-ld-path) + unset FULL_LD_PATH + ;; + -i|--ignore) + remove_old_tempfiles=1 + ;; + -k|--keep-temp) + KEEP_TEMP=1 + ;; + -vv|--extra-verbose|-v|--verbose) + VERBOSE=1 + EMERGE_OPTIONS+=" $1" + ;; + --) + ;; + *) + EMERGE_OPTIONS+=" $1" + ;; + esac + shift + 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 +} +get_args "$@" + +echo "Configuring search environment for $appname" + +# Obey PORTAGE_NICENESS +PORTAGE_NICENESS=$(portageq envvar PORTAGE_NICENESS) +if [[ $PORTAGE_NICENESS ]]; then + renice $PORTAGE_NICENESS $$ > /dev/null + # Since we have already set our nice value for our processes, + # reset PORTAGE_NICENESS to zero to avoid having emerge renice again. + export PORTAGE_NICENESS="0" +fi + +PORTAGE_ROOT=$(portageq envvar ROOT) +PORTAGE_ROOT="${PORTAGE_ROOT:-/}" + +# Update the incremental variables using /etc/profile.env, /etc/ld.so.conf, +# portage, and the environment + +# Read the incremental variables from environment and portage +# Until such time as portage supports these variables as incrementals +# The value will be what is in /etc/make.conf +SEARCH_DIRS+=" "$(unset SEARCH_DIRS; portageq envvar SEARCH_DIRS) +SEARCH_DIRS_MASK+=" "$(unset SEARCH_DIRS_MASK; portageq envvar SEARCH_DIRS_MASK) +LD_LIBRARY_MASK+=" "$(unset LD_LIBRARY_MASK; portageq envvar LD_LIBRARY_MASK) + +# Add the defaults +if [[ -d /etc/revdep-rebuild ]]; then + for file in /etc/revdep-rebuild/*; do + SEARCH_DIRS+=" "$(. $file; echo $SEARCH_DIRS) + SEARCH_DIRS_MASK+=" "$(. $file; echo $SEARCH_DIRS_MASK) + LD_LIBRARY_MASK+=" "$(. $file; echo $LD_LIBRARY_MASK) + done +else + SEARCH_DIRS+=" /bin /sbin /usr/bin /usr/sbin /lib* /usr/lib*" + SEARCH_DIRS_MASK+=" /opt/OpenOffice /usr/lib/openoffice" + LD_LIBRARY_MASK+=" libodbcinst.so libodbc.so libjava.so libjvm.so" +fi + +# Get the ROOTPATH and PATH from /etc/profile.env +if [[ -r "/etc/profile.env" ]]; then + SEARCH_DIRS+=" "$(. /etc/profile.env; /usr/bin/tr ':' ' ' <<< "$ROOTPATH $PATH") +fi + +# Get the directories from /etc/ld.so.conf +if [[ -r /etc/ld.so.conf ]]; then + SEARCH_DIRS+=" "$(sed '/^#/d;s/#.*$//' /etc/ld.so.conf) +fi + +# Set the final variables +SEARCH_DIRS=$(clean_var "$SEARCH_DIRS") +SEARCH_DIRS_MASK=$(clean_var "$SEARCH_DIRS_MASK") +LD_LIBRARY_MASK=$(clean_var "$LD_LIBRARY_MASK") + +# Use the color preference from portage +NOCOLOR=$(portageq envvar NOCOLOR) + +# Find a place to put temporary files +# TODO; let the user choose where to put tempfiles +# gfind $HOME/ /var/tmp/ /tmp/ -writable -print -quit +# TODO: This is a rather noisy, but portable way to implement -quit +LIST=$( + find $HOME/ /var/tmp/ /tmp/ -writable | while read LIST; do + echo "$LIST.$appname" + break + done +) +if [[ $LIST = .$appname ]]; then + die 1 "!!! Unable to find a satisfactory location for temporary files !!!" +fi +[[ $remove_old_tempfiles ]] && rm -f $LIST.* + +function set_trap () { + trap "rm_temp $1" SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM +} +function rm_temp () { + rm $1 + die 1 $' ...terminated.\nRemoving incomplete '"$1." +} +if [[ $SEARCH_BROKEN ]]; then + SONAME_SEARCH="$SONAME" + HEAD_TEXT="broken by a package update" + OK_TEXT="Dynamic linking on your system is consistent" + WORKING_TEXT=" consistency" +else + # first case is needed to test against /path/to/foo.so + if [[ $SONAME = /* ]]; then + # Set to "$SONAME" + SONAME_SEARCH=" $SONAME " + else + # Set to "$SONAME" + SONAME_SEARCH=$'\t'"$SONAME " + fi + # NOTE: Using a redirect instead of echo is good, but it will cause a minor + # incompatibility with older versions of revdep-rebuild, because the + # string sent to md5sum will no longer have a newline at the end. + SOMD5=$(md5sum <<< "$SONAME_SEARCH$SONAME") + LIST+="_${SOMD5:0:8}" + HEAD_TEXT="using $SONAME" + OK_TEXT="There are no dynamic links to $SONAME" + unset WORKING_TEXT SOMD5 +fi + +[[ $LIST ]] || die 1 $LIST IS NOT DEFINED + +# If any of our temporary files are older than 1 day, remove them all +[[ ! $keep_tempfiles && -r $LIST && + $( + find -L "$LIST" -type f -mmin +1440 -print | + while read; do echo 1; break; done + ) ]] && 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" + ) ) + IFS="$oIFS" + if [[ ${PREVS[0]} != $SEARCH_DIRS || + ${PREVS[1]} != $SEARCH_DIRS_MASK || + ${PREVS[2]} != $LD_LIBRARY_MASK || + ${PREVS[3]} != $PORTAGE_ROOT ]]; then + echo 'Environment mismatch from previous run, deleting temporary files...' + rm -f $LIST* + fi + unset PREVS +fi + +# Log the current environment +cat > "$LIST.0_env" <<- EOF + SEARCH_DIRS="$SEARCH_DIRS" + SEARCH_DIRS_MASK="$SEARCH_DIRS_MASK" + LD_LIBRARY_MASK="$LD_LIBRARY_MASK" + PORTAGE_ROOT="$PORTAGE_ROOT" + EMERGE_OPTIONS="$EMERGE_OPTIONS" +EOF + +if [[ $VERBOSE ]]; then + echo + echo "$appname environment:" + cat $LIST.0_env +fi + +cat <<- EOF + + Checking reverse dependencies... + + Packages containing binaries and libraries $HEAD_TEXT + will be emerged. + +EOF +color_echo green -n "Collecting system binaries and libraries..." + +if [[ -r $LIST.1_files ]]; then + echo " using existing $LIST.1_files." +else + # Be safe and remove any extraneous temporary files + rm -f $LIST.[1-9]_* + + set_trap "$LIST.1_*" + + findMask=($SEARCH_DIRS_MASK) + findMask="${findMask[@]/#/-o -path }" + findMask="${findMask#-o }" + find ${SEARCH_DIRS[@]} \( $findMask \) -prune -o -type f \( -executable -o \ + -name '*.so' -o -name '*.so.*' -o -name '*.la' \) -print 2> /dev/null | + sort -u > $LIST.1_files + echo -e " done.\n ($LIST.1_files)" +fi + +if [[ $SEARCH_BROKEN && $FULL_LD_PATH ]]; then + echo + color_echo green -n 'Collecting complete LD_LIBRARY_PATH...' + if [[ -f $LIST.2_ldpath ]] ; then + echo " using existing $LIST.2_ldpath." + COMPLETE_LD_LIBRARY_PATH=$(<"$LIST.2_ldpath") + else + set_trap "$LIST.2_ldpath" + # Ensure that the "trusted" lib directories are at the start of the path + COMPLETE_LD_LIBRARY_PATH=( + /lib* + /usr/lib* + $(sed '/^#/d;s/#.*$//' < /etc/ld.so.conf) + $(sed 's:/[^/]*$::' < "$LIST.1_files" | sort -ru) + ) + oIFS="$IFS"; IFS=':' + COMPLETE_LD_LIBRARY_PATH="${COMPLETE_LD_LIBRARY_PATH[*]}" + IFS="$oIFS" + echo "$COMPLETE_LD_LIBRARY_PATH" > "$LIST.2_ldpath" + echo -e " done.\n ($LIST.2_ldpath)" + fi +fi + +echo +color_echo green -n "Checking dynamic linking$WORKING_TEXT..." +if [[ -s $LIST.3_rebuild ]]; then + echo " using existing $LIST.3_rebuild." +else + [[ $LIST ]] || die 1 "$LIST" 'is undefined! (This is a bug.)' + echo_v + set_trap "$LIST.3_rebuild" + rm -f $LIST.3* + files=($(<"$LIST.1_files")) + numFiles=${#files[@]}; i=0 + + for FILE in ${files[@]}; do + if [[ $FILE != *.la ]]; then + # Note: double checking seems to be faster than single with complete path + # (special add ons are rare). + ldd_output=$(ldd "$FILE" 2>> "$LIST.3_ldd_errors" | sort -u) + ldd_status=$? # TODO: Check this for problems with sort + if grep -vF "$LD_LIBRARY_MASK" <<< "$ldd_output" | + grep -q "$SONAME_SEARCH"; then + if [[ $SEARCH_BROKEN && $FULL_LD_PATH ]]; then + + if LD_LIBRARY_PATH="$COMPLETE_LD_LIBRARY_PATH" ldd "$FILE" 2>/dev/null | + grep -v "$LD_LIBRARY_MASK" | grep -q "$SONAME_SEARCH"; then + # FIXME: I hate duplicating code + # Only build missing direct dependencies + MISSING_LIBS=$( + expr='s/[[:space:]]*\([^[:space:]]*\) => not found/\1/p' + sed -n "$expr" <<< "$ldd_output" + ) + REQUIRED_LIBS=$( + expr='s/^[[:space:]]*NEEDED[[:space:]]*\([^[:space:]]*\).*/\1/p'; + objdump -x "$FILE" | sed "$expr" | sort -u + ) + MISSING_LIBS=$(grep -F "$REQUIRED_LIBS" <<< "$MISSING_LIBS") + if [[ $MISSING_LIBS ]]; then + echo "obj $FILE" >> "$LIST.3_rebuild" + echo_v " broken $FILE (requires $MISSING_LIBS)" + fi + fi + else + # FIXME: I hate duplicating code + # Only rebuild for direct dependencies + MISSING_LIBS=$( + expr="/$SONAME_SEARCH/s/^\([^[:space:]]*\).*$/\1/p" + sort -u <<< "$ldd_output" | sed -n "$expr" + ) + REQUIRED_LIBS=$( + expr='s/^[[:space:]]*NEEDED[[:space:]]*\([^[:space:]]*\).*/\1/p'; + objdump -x "$FILE" | sed "$expr" | sort -u + ) + MISSING_LIBS=$(grep -F "$REQUIRED_LIBS") + if [[ $MISSING_LIBS ]]; then + echo "obj $FILE" >> "$LIST.3_rebuild" + if [[ $SEARCH_BROKEN ]]; then + echo_v " broken $FILE (requires $MISSING_LIBS)" + else + echo_v " found $FILE" + fi + fi + fi + fi + elif [[ $SEARCH_BROKEN ]]; then + # Look for broken .la files + for depend in $( + awk -F"[=']" '/^dependency_libs/{ + gsub("^-[^[:space:]]*", "", $2); + gsub("[[:space:]]-[^[:space:]]*", "", $2); + print $2 + }' "$FILE" + ); do + if [[ $depend != /* && ! -e $depend ]]; then + echo "obj $FILE" >> "$LIST.3_rebuild" + echo_v " broken $FILE (requires $depend)" + fi + done + fi + [[ $VERBOSE ]] && + progress $((++i)) $numFiles $FILE || + progress $((++i)) $numFiles + done + if [[ $SEARCH_BROKEN ]]; then + # Look for missing version + for FILE in $( + awk '/no version information available/{ + gsub("[()]", "", $NF); + print $NF + }' "$LIST.3_ldd_errors" | sort -u + ); do + echo "obj $FILE" >> "$LIST.3_rebuild" + echo_v " broken $FILE (no version information available)" + done + fi + [[ -s $LIST.3_rebuild ]] || clean_exit + echo -e " done.\n ($LIST.3_rebuild)" +fi + +if [[ $PACKAGE_NAMES ]]; then + echo + color_echo green -n 'Assigning files to packages...' + if [[ -r $LIST.4_packages_raw ]]; then + echo " using existing $LIST.4_packages_raw." + else + set_trap "$LIST.4_packages*" + rm -f $LIST.4* + while read obj FILE; do + if [[ $PORTAGE_UTILS ]]; then + EXACT_PKG=$(qfile -qvC $FILE) + elif [[ $PKGCORE ]]; then + EXACT_PKG=$(pquery --nocolor --owns="$FILE") + elif [[ $EQUERY ]]; then + EXACT_PKG=$(equery -q -C b $FILE) + else + EXACT_PKG=$( + find /var/db/pkg -name CONTENTS | + xargs grep -Fl "obj $FILE " | + sed -e 's:/var/db/pkg/\(.*\)/CONTENTS:\1:g' + ) + fi + if [[ $EXACT_PKG ]]; then + # Strip version information + PKG="${EXACT_PKG%%-r[[:digit:]]*}" + PKG="${PKG%-*}" + echo "$EXACT_PKG" >> $LIST.4_packages_raw + echo "$FILE -> $EXACT_PKG" >> $LIST.4_package_owners + echo_v -n -e "\n $FILE -> $PKG" + else + color_echo -n -e "\n *** $FILE not owned by any package is broken! ***" + echo "$FILE -> (none)" >> $LIST.4_package_owners + echo_v -n -e "\n $FILE -> (none)" + fi + done < "$LIST.3_rebuild" + echo_v + echo -e " done.\n ($LIST.4_packages_raw, $LIST.4_package_owners)" + fi + + echo + color_echo green -n "Cleaning list of packages to rebuild..." + if [[ -f $LIST.4_packages ]]; then + echo " using existing $LIST.4_packages." + else + sort -u $LIST.4_packages_raw > $LIST.4_packages + echo -e " done.\n ($LIST.4_packages)" + fi + + echo + color_echo green -n 'Assigning packages to ebuilds...' + if [[ -f $LIST.4_ebuilds ]]; then + echo " using existing $LIST.4_ebuilds." + else + if [[ -s $LIST.4_packages ]]; then + set_trap "$LIST.4_ebuilds" + while read EXACT_PKG; do + # Get the slot + PKG="${EXACT_PKG%%-r[[:digit:]]*}" + PKG="${PKG%-*}" + SLOT=$( "$LIST.4_ebuilds" + echo -e " done.\n ($LIST.4_ebuilds)" + else + echo " Nothing to rebuild" + rm -f "$LIST.4_ebuilds" + fi + fi +else + echo + color_echo green -n 'Assigning files to ebuilds...' + if [[ -r $LIST.4_ebuilds ]]; then + echo " using existing $LIST.4_ebuilds." + else + if [[ -s $LIST.3_rebuild ]]; then + rebuildList=" $(<"$LIST.3_rebuild") " + rebuildList="${rebuildList//[[:space:]]obj[[:space:]]/ }" + if [[ $PORTAGE_UTILS ]]; then + qfile -qvC $rebuildList # Don't put quotes around $rebuildList + # elif [[ $PKGCORE ]]; then + # This is really slow... + # pquery --nocolor --early-out --vdb --owns-re="(${rebuildList//[[:space:]]/|})" + # elif [[ $EQUERY ]]; then + # equery can't seem to do this operation on multiple args at all + else + find /var/db/pkg -name CONTENTS | + xargs grep -Fl "$rebuildList" | + sed 's:/var/db/pkg/\(.*\)/CONTENTS:=\1:' + fi > $LIST.4_ebuilds + echo -e " done.\n ($LIST.4_ebuilds)" + else + echo " Nothing to rebuild" + rm -f $LIST.4_ebuilds + fi + fi +fi + +if [[ $order_packages ]]; then + color_echo green -n $'\nEvaluating package order...' + if [[ -r $LIST.5_order ]]; then + echo " using existing $LIST.5_order." + else + set_trap "$LIST.5_order" + RAW_REBUILD_LIST=$(<"$LIST.4_ebuilds") + if [[ $RAW_REBUILD_LIST ]]; then + OLD_EMERGE_DEFAULT_OPTS="$EMERGE_DEFAULT_OPTS" + export EMERGE_DEFAULT_OPTS="--nospinner --pretend --oneshot --nodeps --quiet" + RAW_REBUILD_LIST="=${RAW_REBUILD_LIST//[[:space:]]/ =}" + REBUILD_GREP=$(emerge $RAW_REBUILD_LIST | awk '{print $NF}') && + emerge --deep $RAW_REBUILD_LIST | awk '{print $NF}' | + grep -F "$REBUILD_GREP" > $LIST.5_order || { + set_color red + cat <<- EOF + Warning: Failed to resolve package order. + Will merge in "random" order! + EOF + set_color + cat <<- EOF + Possible reasons: + - An ebuild is no longer in the portage tree. + - An ebuild is masked, use /etc/portage/packages.keyword + and/or /etc/portage/package.unmask to unmask it + EOF + for i in {1..5}; do + echo -n -e '\a.' + sleep 1 + done + } + export EMERGE_DEFAULT_OPTS="$OLD_EMERGE_DEFAULT_OPTS" + else + rm -f "$LIST.5_order" + fi + [[ -f $LIST.5_order ]] && echo -e " done.\n ($LIST.5_order)" || + echo -e " done.\n ($LIST.4_ebuilds)" + fi +else + color_echo green "Skipping package ordering" +fi + +# Clean up no longer needed environment variables +unset COMPLETE_LD_LIBRARY_PATH SEARCH_DIRS SEARCH_DIRS_MASK LD_LIBRARY_MASK PORTAGE_ROOT + +[[ -f $LIST.5_order ]] && REBUILD_LIST=$(<"$LIST.5_order") || + REBUILD_LIST=$(<"$LIST.4_ebuilds") + +trap - SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM + +REBUILD_LIST="=${REBUILD_LIST//[[:space:]]/ =}" + +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..." + +echo "emerge --oneshot $EMERGE_OPTIONS $REBUILD_LIST" + +if [[ $IS_REAL_MERGE ]]; then + for i in {1..10}; do + echo -n -e '\a.' + sleep 1 + done + echo +fi + +# Link file descriptor #6 with stdin so --ask will work +exec 6<&0 + +# Run in background to correctly handle Ctrl-C +{ + EMERGE_DEFAULT_OPTS="" emerge --oneshot $EMERGE_OPTIONS $REBUILD_LIST <&6 + echo $? > $LIST.6_status +} & +wait + +# Now restore stdin from fd #6, where it had been saved, and close fd #6 ( 6<&- ) to free it for other processes to use. +exec 0<&6 6<&- + +if (( $(<"$LIST.6_status") != 0 )); then + set_color red + cat <<- EOF + + revdep-rebuild failed to emerge all packages. + you have the following choices: + + EOF + set_color + cat <<- EOF + - if emerge failed during the build, fix the problems and re-run revdep-rebuild + or + - use -X or --package-names as first argument (trys to rebuild package, not exact + ebuild) + or + - set ACCEPT_KEYWORDS=\"~\" 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 +else + if [[ $IS_REAL_MERGE ]]; then + 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