-#! /bin/bash
-#Shows unrequired packages and missing dependencies.
-#Author/Maintainer: Brandon Low <lostlogic@gentoo.org>
-#Author: Jerry Haltom <ssrit@larvalstage.net>
-
-PROG=`basename ${0}`
-
-tmp="/tmp/$$"
-
-#Get PORTDIR_OVERLAY from portage
-PORTDIR_OVERLAY="$(/usr/lib/portage/bin/portageq portdir_overlay)"
-
-rm -rf ${tmp} > /dev/null 2>&1
-mkdir ${tmp} > /dev/null 2>&1
-
-declare -i i
-
-set -- `getopt -n ${PROG} -o N,R,U,I,v,q,C,h -l needed,removed,unneeded,interactive,verbose,quiet,nocolor,help -- ${*/ --/};[ $? != 0 ] && echo "y"`
-
-while [ ${#} -gt 0 ]
-do
- a=${1}
- shift
- case "${a}" in
-
- -I|--interactive)
- interactive=y
- ;;
-
- -N|--needed)
- needed=y
- ;;
-
- -U|--unneeded)
- unneeded=y
- ;;
-
- -R|--removed)
- removed=y
- ;;
-
- -v|--verbose)
- verb=y
- ;;
-
- -q|--quiet)
- quiet=y
- ;;
-
- -C|--nocolor)
- nocolor=y
- ;;
-
- -h|--help)
- usage=y
- ;;
-
- --)
- [ ${1} ] && usage=y && broke=y
- break
- ;;
-
- *)
- usage=y
- broke=y
- echo "FIXME - OPTION PARSING - ${a}"
- break
- ;;
-
- esac
-done
-
-if [ ! ${needed} ] && [ ! ${unneeded} ] && [ ! ${removed} ]; then
- needed=y
- unneeded=y
- removed=y
-fi
-
-#Set up colors
-if [ ! "${nocolor}" ]; then
- 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"
-elif [ ${quiet} ] && (
- ( [ ${needed} ] && [ ${unneeded} ] ) ||
- ( [ ${unneeded} ] && [ ${removed} ] ) ||
- ( [ ${removed} ] && [ ${needed} ] )
- ); then
- NEED=" N"
- UNNE=" U"
- REMO=" R"
-fi
-
-if [ ${usage} ]; then
- echo -e "${BR}GenToolKit's Dependency Checker!
-${NO}Displays packages that are installed but which none
-of the packages in world or system depend on, and
-displays packages which are depended on by world or
-system, but are not currently installed.
-
-${BR}USAGE:
- ${BL}${PROG}${YL} [${NO}options${YL}]${NO}
- ${BL}${PROG}${GR} --help${NO}
-
-${BR}OPTIONS:
- ${GR}-U, --unneeded${NO} display unneeded packages that are installed (${GR}green${NO})
- ${GR}-N, --needed${NO} display needed packages that are not installed (${RD}red${NO})
- ${GR}-R, --removed${NO} display installed packages not in portage (${YL}yellow${NO})
-
- ${GR}-I, --interactive${NO} interactively modify world file before proceeding
- ${GR}-C, --nocolor${NO} output without color, if necessary, package types are
- noted with ${GR}U, N${NO} and ${GR}R${NO} respectively
- ${GR}-v, --verbose${NO} be more verbose
- ${GR}-q, --quiet${NO} be quiet (just output the packages, no extra info)
-
-${BR}NOTES:
- ${GR}*${NO} If this script is run on a system that is not up-to-date or which hasn't
- been cleaned (with '${BL}emerge -c${NO}') recently, the output may be deceptive.
- ${GR}*${NO} If the same package name appears in all three categories, then it is
- definitely time to update that package and then run '${BL}emerge -c${NO}'.
- ${GR}*${NO} The ${GR}-U, -N${NO} and ${GR}-R${NO} options may be combined, defaults to ${GR}-UNR${NO}"
- rm -rf ${tmp} > /dev/null 2>&1
- [ ${broke} ] && exit 1 || exit 0
-fi
-
-X="\([^/]*\)"
-
-#Retrieve currently merged packages.
-if [ ${verb} ];then
- echo -e "${CY}Retrieving currently merged packages.${NO}"
-fi
-find /var/db/pkg -name '*.ebuild' | \
- sed -e "s:/var/db/pkg/::" \
- -e "s:${X}/${X}/${X}:\1/\2:" | \
- sort | uniq >> ${tmp}/current
-
-if [ ${verb} ]; then
- echo -e "${CY}"`cat ${tmp}/current | wc -l` "currently merged packages.${NO}"
- echo -e
-fi
-
-#Retrieve system packages and add to image.
-if [ ${verb} ];then
- echo -e "${CY}Retrieving system packages.${NO}"
-fi
-emerge system -eup | \
- sed -e "/ebuild/s:^.*] \([^ ]*\) *:\1:p;d" | \
- sort | uniq \
- > ${tmp}/system
-
-if [ ${verb} ]; then
- echo -e "${CY}"`cat ${tmp}/system | wc -l 2> /dev/null` "packages contained in system.${NO}"
- echo -e
- echo -e "${CY}Preparing world file.${NO}"
-fi
-
-#Create local copy of world and ask user to verify it.
-cp /var/cache/edb/world ${tmp}/world
-
-if [ ${interactive} ]; then
- ${EDITOR} ${tmp}/world
-fi
-
-#Retrieve world packages and dependencies and add to image.
-if [ ${verb} ]; then
- echo -e
- echo -e "${CY}Preparing list of installed world packages.${NO}"
- echo -e
-fi
-
-cat ${tmp}/current | grep -f ${tmp}/world | sort > ${tmp}/world.inst
-find /usr/portage ${PORTDIR_OVERLAY} -iname '*.ebuild' | \
- cut -f4,6 -d/ | sed -e 's:\.ebuild::' > ${tmp}/ebuilds
-grep -xf ${tmp}/world.inst ${tmp}/ebuilds >> ${tmp}/world.new
-
-if [ ${verb} ]; then
- echo -e "${CY}"`cat ${tmp}/ebuilds | wc -l`"\tebuilds available.${NO}"
- echo -e "${CY}"`cat ${tmp}/world.new | wc -l`"\tpackages contained in final world file.${NO}"
- echo -e
- echo -e "${CY}List prepared, checking dependencies with emerge -eup${NO}"
-fi
-
-sort ${tmp}/world.new |sed -e 's:^:\\\=:' | uniq | xargs emerge -eup | \
- tee ${tmp}/log | sed -e '/ebuild/s:^.*] \([^ ]*\) *$:\1:p;d' > ${tmp}/image.unsorted
-
-depends=`cat ${tmp}/image.unsorted|wc -l`
-
-if [ ${depends} -lt "2" ]; then
- echo -e "${RD}There appears to be an unresolved dependency in your world file."
- echo -e "Please check for masking errors or other world file issues,"
- echo -e "and then try again."
- echo -e
- echo -e "The following is the emerge output for your reference:${NO}"
- cat ${tmp}/log
- rm -rf ${tmp} > /dev/null 2>&1
- exit 1
-fi
-
-cat ${tmp}/system >> ${tmp}/image.unsorted
-
-#Cleanup image
-sort ${tmp}/image.unsorted | uniq > ${tmp}/image
-
-if [ ${verb} ];then
- echo -e "${CY}"`cat ${tmp}/image | wc -l` "packages contained in final image.${NO}"
- echo -e
-fi
-
-#Determine packages that exist in current but not in image.
-#These packages are safe to clean up.
-if [ ${unneeded} ]; then
- if [ ! ${quiet} ]; then
- echo -e "${CY}These packages have no other packages depending on them.${NO}"
- fi
-
- grep -vxf ${tmp}/image ${tmp}/current > ${tmp}/unneeded
- for line in `cat ${tmp}/unneeded`;do
- echo -e "${GR}${line}${CY}${UNNE}${NO}"
- done
-
- if [ ! ${quiet} ];then
- echo -e "${CY}Total of"`cat ${tmp}/unneeded|wc -l` "unneeded packages.${NO}"
- fi
-fi
-
-#Determine packages that exist in image but not in current.
-#These packages should be added.
-if [ ${needed} ]; then
- if [ ! ${quiet} ];then
- echo -e
- echo -e "${CY}These packages are depended upon but are not present on the system.${NO}"
- fi
-
- grep -vxf ${tmp}/current ${tmp}/image > ${tmp}/needed
- for line in `cat ${tmp}/needed`;do
- echo -e "${RD}${line}${CY}${NEED}${NO}"
- done
-
- if [ ! ${quiet} ];then
- echo -e "${CY}Total of"`cat ${tmp}/needed|wc -l` "needed packages.${NO}"
- fi
-fi
-
-#Determine packages that are installed but not currently in portage
-if [ ${removed} ]; then
- if [ ! ${quiet} ];then
- echo -e
- echo -e "${CY}These packages are installed but not in the portage tree.${NO}"
- fi
- grep -xf ${tmp}/current ${tmp}/ebuilds > ${tmp}/hascurrent
- grep -vxf ${tmp}/hascurrent ${tmp}/current > ${tmp}/removed
- for line in `cat ${tmp}/removed`;do
- echo -e "${YL}${line}${CY}${REMO}${NO}"
- done
-
- if [ ! ${quiet} ];then
- echo -e "${CY}Total of"`cat ${tmp}/removed|wc -l` "removed packages.${NO}"
- fi
-fi
-
-rm -rf ${tmp} > /dev/null 2>&1
+#! /usr/bin/env python2.2
+
+# Terminology:
+#
+# portdir = /usr/portage + /usr/local/portage
+# vardir = /var/db/pkg
+
+import sys
+import gentoolkit
+from output import *
+
+__author__ = "Karl Trygve Kalleberg, Brandon Low, Jerry Haltom"
+__email__ = "karltk@gentoo.org, lostlogic@gentoo.org, ssrit@larvalstage"
+__version__ = "0.2.0"
+__productname__ = "dep-clean"
+__description__ = "Portage auxiliary dependency checker"
+
+class Config:
+ pass
+
+def defaultConfig():
+ Config.displayUnneeded = 1
+ Config.displayNeeded = 1
+ Config.displayRemoved = 1
+ Config.color = -1
+ Config.verbosity = 2
+ Config.prefixes = { "R" : "",
+ "U" : "",
+ "N" : "" }
+def asCPVs(pkgs):
+ return map(lambda x: x.get_cpv(), pkgs)
+
+def asCPs(pkgs):
+ return map(lambda x: x.get_cp(), pkgs)
+
+def toCP(cpvs):
+ def _(x):
+ (c,p,v,r) = gentoolkit.split_package_name(x)
+ return c + "/" + p
+ return map(_, cpvs)
+
+def checkDeps():
+ if Config.verbosity > 1:
+ print "Scanning packages, please be patient..."
+
+ unmerged = asCPVs(gentoolkit.find_all_uninstalled_packages())
+ unmerged_cp = toCP(unmerged)
+
+ merged = asCPVs(gentoolkit.find_all_installed_packages())
+ merged_cp = toCP(merged)
+
+ (system, unres_system) = gentoolkit.find_system_packages()
+ system = asCPVs(system)
+
+ (world, unres_world) = gentoolkit.find_world_packages()
+ world = asCPVs(world)
+
+ desired = system + world
+
+ unneeded = filter(lambda x: x not in desired, merged)
+ needed = filter(lambda x: x not in merged, desired)
+ old = filter(lambda x: x not in unmerged_cp, merged_cp)
+
+ if len(needed):
+ print "Packages required, but not by world and system:"
+ for x in needed: print " " + x
+ raise "Internal error, please report."
+
+ if len(unres_system) and Config.displayNeeded:
+ if Config.verbosity > 0:
+ print white("Packages in system but not installed:")
+ for x in unres_system:
+ print " " + Config.prefixes["N"] + red(x)
+
+ if len(unres_world) and Config.displayNeeded:
+ if Config.verbosity > 0:
+ print white("Packages in world but not installed:")
+ for x in unres_world:
+ print " " + Config.prefixes["N"] + red(x)
+
+ if len(old) and Config.displayRemoved:
+ if Config.verbosity > 0:
+ print white("Packages installed, but no longer available:")
+ for x in old:
+ print " " + Config.prefixes["R"] + yellow(x)
+
+ if len(unneeded) and Config.displayUnneeded:
+ if Config.verbosity > 0:
+ print white("Packages installed, but not required by system or world:")
+ for x in unneeded:
+ print " " + Config.prefixes["U"] + green(x)
+
+def main():
+
+ defaultConfig()
+
+ for x in sys.argv:
+ if 0:
+ pass
+ elif x in ["-h","--help"]:
+ printUsage()
+ sys.exit(0)
+ elif x in ["-V","--version"]:
+ printVersion()
+ sys.exit(0)
+
+ elif x in ["-n","--needed","--needed=yes"]:
+ Config.displayNeeded = 1
+ elif x in ["-N","--needed=no"]:
+ Config.displayNeeded = 0
+
+ elif x in ["-u","--unneeded","--unneeded=yes"]:
+ Config.displayUnneeded = 1
+ elif x in ["-U","--unneeded=no"]:
+ Config.displayUnneeded = 0
+
+ elif x in ["-r","--removed","--removed=yes"]:
+ Config.displayRemoved = 1
+ elif x in ["-R","--removed","--removed=no"]:
+ Config.displayRemoved = 0
+ elif x in ["-c","--color=yes"]:
+ Config.color = 1
+ elif x in ["-C","--color=no"]:
+ Config.color = 0
+
+ elif x in ["-v", "--verbose"]:
+ Config.verbosity += 1
+ elif x in ["-q", "--quiet"]:
+ Config.verbosity = 0
+
+ # Set up colour output correctly
+ if (Config.color == -1 and \
+ ((not sys.stdout.isatty()) or \
+ (gentoolkit.settings["NOCOLOR"] in ["yes","true"]))) \
+ or \
+ Config.color == 0:
+ nocolor()
+ Config.prefixes = { "R": "R ", "N": "N ", "U": "U " }
+
+ checkDeps()
+
+def printVersion():
+ print __productname__ + "(" + __version__ + ") - " + \
+ __description__
+ print "Authors: " + __author__
+
+def printUsage():
+ print white("Usage: ") + turquoise(__productname__) + \
+ " [" + turquoise("options") + "]"
+ print "Where " + turquoise("options") + " is one of:"
+ print white("Display:")
+ print " -N,--needed needed packages that are not installed."
+ print " -R,--removed installed packages not in portage."
+ print " -U,--unneeded potentially unneeded packages that are installed."
+ print white("Other:")
+ print " -C,--nocolor output without color. Categories will be denoted by P,N,U."
+ print " -h,--help print this help"
+ print " -v,--version print version information"
+
+if __name__ == "__main__":
+ main()