Added reverse dependency fix script by utx
authorliquidx <liquidx@gentoo.org>
Thu, 8 May 2003 11:25:30 +0000 (11:25 -0000)
committerliquidx <liquidx@gentoo.org>
Thu, 8 May 2003 11:25:30 +0000 (11:25 -0000)
svn path=/; revision=25

trunk/README
trunk/src/etcat/etcat
trunk/src/revdep-rebuild/AUTHORS [new file with mode: 0644]
trunk/src/revdep-rebuild/README [new file with mode: 0644]
trunk/src/revdep-rebuild/revdep-rebuild [new file with mode: 0755]

index cd3a69562ea328ca3ee2003a38c6afcf3485f192..031186d236f73d94555da237bcba392ccbfcda0d 100644 (file)
@@ -17,11 +17,13 @@ dep-clean           - cleans out unwanted dependencies
 emerge-rsync        - coloured output of changes in last rsync
 emerge-webrsync     - rsync-over-http 
 epm                 - rpm-like query tool
+etcat               - extracts auxillary information from portage
 etc-update          - keeps your /etc up to date after package installs
 pkg-clean           - cleans packages
 pkg-size            - calculates size of an installed package
 portage-statistics  - shows various statistics about the Portage Tree
 qpkg                - convient package query tool
+revdep-rebuild      - scans/fixes broken shared libs and binaries
 useflag             - tool for handling use flag settings
 
 
index ea29beb2f2f1108a048d686217af3d8ed0fc5bf9..594c9530225337a8adfdd550d10db143de9fc17f 100755 (executable)
@@ -867,8 +867,8 @@ def depends(query):
         # for each category, we just grep for the deps, slowly
         for dep in os.listdir(portage.root + "var/cache/edb/dep/" + x):
             f = open("%s/var/cache/edb/dep/%s/%s" % (portage.root, x, dep))
+           depend = f.readline()
             rdepend = f.readline()
-            depend = f.readline()
            f.close()
            match = isdepend.search(rdepend)
            if match:
diff --git a/trunk/src/revdep-rebuild/AUTHORS b/trunk/src/revdep-rebuild/AUTHORS
new file mode 100644 (file)
index 0000000..4a74e2e
--- /dev/null
@@ -0,0 +1 @@
+Stanislav Brabec <utx@gentoo.org>
diff --git a/trunk/src/revdep-rebuild/README b/trunk/src/revdep-rebuild/README
new file mode 100644 (file)
index 0000000..a122f20
--- /dev/null
@@ -0,0 +1,8 @@
+This tool scans libraries and binaries for broken shared lib dependencies
+and fixes them by re-emerging those broken binaries and shared libraries.
+
+It is a temporary stop-gap measure to fix installations that break when a
+core-library needs to be upgraded along with all its dependencies. Hopefully
+we will not need this when we get reverse dependencies into portage.
+
+- Alastair Tse <liquidx@gentoo.org>
diff --git a/trunk/src/revdep-rebuild/revdep-rebuild b/trunk/src/revdep-rebuild/revdep-rebuild
new file mode 100755 (executable)
index 0000000..0b5138d
--- /dev/null
@@ -0,0 +1,269 @@
+#! /bin/bash
+
+# Copyright 1999-2003 Gentoo Technologies, Inc.
+# $Header$
+# Author: Stanislav Brabec <utx@gentoo.org>
+
+# requires: qpkg
+
+# FIXME: Rebuild order should follow DEPEND tree, otherwise packages
+# can be rebuild incorrectly or fail.
+
+# Mask of specially evaluated libraries (exactly one space separated).
+LD_LIBRARY_MASK="libodbcinst.so libodbc.so libjava.so libjvm.so"
+
+# Base of temporary files names.
+LIST=~/.reverse-dep-shlib-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
+
+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 "  -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 <utx@gentoo.org>"
+           exit 0
+           ;;
+       -X | --package-names )
+           PACKAGE_NAMES=true
+           shift
+           ;;
+       -q | --quiet )
+           alias echo_v=:
+           shift
+           ;;
+       -- )
+           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
+}
+
+echo
+echo "Checking reverse dependencies..."
+echo "Packages containing binaries and libraries broken by any package update,"
+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"
+# Note /usr/libexec and /usr/local/subprefix cotradicts FHS, but are present
+    find /lib /bin /sbin /usr/lib /usr/bin /usr/sbin /usr/libexec /usr/X11R6/lib /usr/X11R6/bin /usr/X11R6/sbin /usr/local /usr/kde/*/lib /usr/*-*-linux-gnu /opt -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
+
+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/#.*$//' </etc/ld.so.conf
+    ) | uniq | sort | uniq |
+    tr '\n' : | tr -d '\r' | sed 's/:$//' >$LIST.2_ldpath
+    echo -e " done.\n  ($LIST.2_ldpath)"
+fi
+export COMPLETE_LD_LIBRARY_PATH="$(cat $LIST.2_ldpath)"
+
+echo
+echo -n -e "${GR}Checking dynamic linking consistency...${NO}"
+if [ -f $LIST.3_broken ] ; then
+    echo " using existing $LIST.3_broken."
+else
+    echo_v
+    set_trap "$LIST.3_broken"
+    LD_MASK="\\(       $(echo "$LD_LIBRARY_MASK" | sed 's/\./\\./g;s/ / \\|    /g') \\)"
+    echo -n >$LIST.3_broken
+    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" |
+           fgrep -q 'not found' ; then
+           if LD_LIBRARY_PATH="$COMPLETE_LD_LIBRARY_PATH" \
+               ldd "$FILE" 2>/dev/null | grep -v "$LD_MASK" |
+               fgrep -q 'not found' ; then
+               echo "$FILE" >>$LIST.3_broken
+               echo_v "  broken $FILE (requires $(ldd "$FILE" | sed -n 's/     \(.*\) => not found$/\1/p' | tr '\n' ' ' | sed 's/ $//' ))"
+           fi
+       fi
+    done
+    echo -e " done.\n  ($LIST.3_broken)"
+fi
+
+if $PACKAGE_NAMES ; then
+    EXACT_EBUILDS=false
+
+    echo
+    echo -n -e "${GR}Assigning files to packages...${NO}"
+    if [ -f $LIST.4_packages_raw ] ; then
+       echo " using existing $LIST.4_packages_raw."
+    else
+       set_trap "$LIST.4_packages_raw"
+       echo -n >$LIST.4_packages_raw
+       echo -n >$LIST.4_package_owners
+       cat $LIST.3_broken | 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)" >> $LIST.4_package_owners            
+               echo_v -n -e "\n  $FILE -> (none)"
+           else
+               echo "$PKG" >> $LIST.4_packages_raw
+               echo "$FILE -> $PKG" >> $LIST.4_package_owners      
+               echo_v -n -e "\n  $FILE -> $PKG"
+           fi
+       done
+       echo_v
+       echo -e " done.\n  ($LIST.4_packages_raw, $LIST.4_package_owners)"
+    fi
+
+    echo
+    echo -n -e "${GR}Cleaning list of packages to rebuild...${NO}"
+    if [ -f $LIST.5_packages ] ; then
+       echo " using existing $LIST.5_packages."
+    else
+       set_trap "$LIST.5_packages"
+       sort <$LIST.4_packages_raw | uniq >$LIST.5_packages
+       echo -e " done.\n  ($LIST.5_packages)"
+    fi
+
+    REBUILD_LIST="$(cat $LIST.5_packages | tr '\n' ' ')"
+
+else
+    EXACT_EBUILDS=true
+
+    echo
+    echo -n -e "${GR}Assigning files to ebuilds...${NO}"
+    if [ -f $LIST.4_ebuilds ] ; then
+       echo " using existing $LIST.4_ebuilds."
+    else
+       set_trap "$LIST.4_ebuilds"
+       cat $LIST.3_broken | sed 's/^/obj /;s/$/ /' |
+       (
+           cd /var/db/pkg
+           fgrep -l -f - */*/CONTENTS
+       ) | sed s:/CONTENTS:: > $LIST.4_ebuilds
+       echo -e " done.\n  ($LIST.4_ebuilds)"
+    fi
+
+    REBUILD_LIST="$(cat $LIST.4_ebuilds | sed s/^/=/ | tr '\n' ' ')"
+fi
+
+trap - SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM
+
+if [ -z "$REBUILD_LIST" ] ; then
+    echo -e "\n${GR}Dynamic linking on your system is consistent... All done.${NO} "
+    rm $LIST.?_*
+    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 $? >$LIST.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 $LIST.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 this script"
+    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.?_*
+       echo "You can re-run this script 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 the script.${NO}"
+    fi
+fi