From: karltk Date: Sun, 27 Jul 2003 12:14:33 +0000 (-0000) Subject: Preparing for Gentoolkit relaunch; added basic gentoolkit library. X-Git-Tag: gentoolkit-0.2.4.3~469 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=69fe0b3c63d2a8cde4c9767c82f551f1ccbeca2b;p=gentoolkit.git Preparing for Gentoolkit relaunch; added basic gentoolkit library. svn path=/; revision=33 --- diff --git a/trunk/src/etcat/etcat b/trunk/src/etcat/etcat index 594c953..f148a1f 100755 --- a/trunk/src/etcat/etcat +++ b/trunk/src/etcat/etcat @@ -42,7 +42,10 @@ # # --| Changes |------------------------------------------------------ # -# * etcat-0.2.0 ( ?? ) +# * etcat-0.3.0 (12 Jul 2003) [karltk] +# - Refactored interesting stuff into the Gentoolkit module +# * etcat-0.2.0 (13 Jun 2003) +# - Updated "versions" with PORTAGE_OVERLAY detection # - Added "graph" feature # * etcat-0.1.5 (30 Apr 2003) # - Fixed disappearing short opts. Oops. @@ -74,7 +77,7 @@ import os,sys,string,re,pprint import getopt,glob -import portage +import gentoolkit from stat import * from output import * @@ -87,7 +90,7 @@ __description__ = "Portage Information Extractor" # .-------------------------------------------------------. # | Initialise Colour Settings | # `-------------------------------------------------------' -if (not sys.stdout.isatty()) or (portage.settings["NOCOLOR"] in ["yes","true"]): +if (not sys.stdout.isatty()) or (gentoolkit.settings["NOCOLOR"] in ["yes","true"]): nocolor() # "option": ("shortcommand","desc",["example one", "example two"]) @@ -99,7 +102,7 @@ options = { "depends":("d","Finds all packages that are directly dependent to a regex search string.", ["etcat depends 'gnome-base/libgnome'", "etcat depends '>=dev-lang/python-2.2'"]), "files":("f","Lists files that belongs to a package and optionally with version.",[]), -"graph":("g","Graphs Dependencies",[]), +"graph":("g","Graphs Dependencies (NON WORKING)",[]), "size":("s","Lists the installed size of a package.",[]), "uses":("u", "Advanced output of USE vars in a package. Tells you flags used by a package at time of installation, flags in current config and flag description.",[]), "versions":("v","Displays the versions available for a specific package. Colour coded to indicate installation status and displays slot information.", @@ -157,99 +160,8 @@ def wrap_print(string, indent=0, width=74): for line in lines: print " "*indent + line -# .-------------------------------------------------------. -# | Smart Pacakge Version Comparison | -# +-------------------------------------------------------+ -# | Does more advanced package sorting hueristics | -# `-------------------------------------------------------' - -LETTERS=map(lambda x: chr(x), range(ord('a'),ord('z'))) -# find roughly which is the newer version -def vercmp(a, b): - a_ver = [] - a_min = "" - a_pre = "" - a_rev = 0 - b_ver = [] - b_min = "" - b_pre = "" - b_rev = 0 - - # split into digestable components - # eg. 1.2.3b_pre4-r5 - # 1. get the 1.2.3 bit - a_parts = a.split("-")[0].split("_") - a_ver = a_parts[0].split(".") - b_parts = b.split("-")[0].split("_") - b_ver = b_parts[0].split(".") - - # 2. get a,b,c.. or whatever letter at the end - if a_ver[-1][-1] in LETTERS: - a_min = a_ver[-1][-1] - a_ver[-1] = a_ver[-1][:-1] - if b_ver[-1][-1] in LETTERS: - b_min = b_ver[-1][-1] - b_ver[-1] = b_ver[-1][:-1] - - # 2. get the _pre4 bit and -r5 - if len(a_parts) > 1: - a_pre = a_parts[1] - if len(a.split("-")) > 1: - a_rev = int(a.split("-")[1][1:]) - if len(b_parts) > 1: - b_pre = b_parts[1] - if len(b.split("-")) > 1: - b_rev = int(b.split("-")[1][1:]) - - # 3. do the comparison - for x in range(len(a_ver)): - # 3a. convert to numbers - try: - a_num = int(a_ver[x]) - except (ValueError, IndexError): - a_num = 0 - try: - b_num = int(b_ver[x]) - except (ValueError, IndexError): - b_num = 0 - # 3b. the comparison - if a_num == b_num: - continue - elif a_num > b_num: - return 1 - elif a_num < b_num: - return -1 - - # 3c. compare minor ver - if a_min and not b_min: - return -1 - elif not a_min and b_min: - return 1 - elif a_min and b_min and a_min > b_min: - return 1 - elif a_min and b_min and a_min < b_min: - return -1 - - # 3d. compare pre ver - if a_pre and not b_pre: - return -1 - elif not a_pre and b_pre: - return 1 - elif a_pre and b_pre and a_pre > b_pre: - return 1 - elif a_pre and b_pre and a_pre < b_pre: - return -1 - - # 3e. compare rev - if a_rev > b_rev: - return 1 - elif a_rev < b_rev: - return -1 - else: - return 0 - - def pkgcmp(a,b): + raise "This is not present" # strips out package name and returns the result of vercmp awords = a.split("-") bwords = b.split("-") @@ -280,7 +192,7 @@ def pkgcmp(a,b): elif bpkg_str > apkg_str: return -1 else: - return vercmp(aver_str, bver_str) + return gentoolkit.compare_versions(aver_str, bver_str) # .-------------------------------------------------------. # | Simple Package Search Function | @@ -290,7 +202,6 @@ def pkgcmp(a,b): # | Results are in the form ["net-www/mozilla"] | # `-------------------------------------------------------' def search(search_key): - matches = [] for package in portage.portdb.cp_all(): package_parts=package.split("/") @@ -311,6 +222,7 @@ def search(search_key): # `-------------------------------------------------------' def smart_pkgsplit(query): + raise "Use something else" cat = '' pkg = '' ver = '' @@ -353,64 +265,10 @@ def smart_pkgsplit(query): # `-------------------------------------------------------' def smart_ebuild(query): - tup = smart_pkgsplit(query) - full_pkg = '' - - # here we have to guess the ebuild we want - if tup[0] and tup[1] and tup[2]: - # we've got all the required fields - if tup[3]: - full_pkg = tup[0] + "/" + tup[1] + "-" + tup[2] + "-" + tup[3] - else: - full_pkg = tup[0] + "/" + tup[1] + "-" + tup[2] - elif tup[1] and tup[2]: - # only got package name and version - matches = search(tup[1] + "$") - print "[ Applications Found : " + white(str(len(matches))) + " ]" - print ">> Using first match only." - if len(matches[0].split("/")) == 2: - if tup[3]: - full_pkg = matches[0] + "-" + tup[2] + "-" + tup[3] - else: - full_pkg = matches[0] + "-" + tup[2] - elif not tup[2]: - # don't have version, so we find the latest version - if tup[0] and tup[1]: - all_vers = portage.portdb.xmatch("match-all",tup[0] + "/" + tup[1]) - elif tup[1]: - all_vers = portage.portdb.xmatch("match-all",tup[1]) - # get fullpkg - full_pkg = portage.portdb.xmatch("bestmatch-list",tup[1],mylist=all_vers) - if not full_pkg: - print "Error: Can't match query:", query - return - else: - print "Error: Can't match query :", query - return - - # find the ebuild - cps = portage.catpkgsplit(full_pkg) - if len(cps) != 4: - print "Error: Something wrong with package found." - return - if cps[3] == "r0": - ebuild = portage.settings["PORTDIR"] + "/" + cps[0] + "/" + cps[1] + "/" + cps[1] + "-" + cps[2] + ".ebuild" - else: - ebuild = portage.settings["PORTDIR"] + "/" + cps[0] + "/" + cps[1] + "/" + cps[1] + "-" + cps[2] + "-" + cps[3] + ".ebuild" - - if os.path.exists(ebuild): - return ebuild - - # can't find it in PORTDIR, so we try the PORTDIR_OVERLAY - if cps[3] == "r0": - ebuild = portage.settings["PORTDIR_OVERLAY"] + "/" + cps[0] + "/" + cps[1] + "/" + cps[1] + "-" + cps[2] + ".ebuild" - else: - ebuild = portage.settings["PORTDIR_OVERLAY"] + "/" + cps[0] + "/" + cps[1] + "/" + cps[1] + "-" + cps[2] + "-" + cps[3] + ".ebuild" - - if os.path.exists(ebuild): - return ebuild - else: - return None + pkg = gentoolkit.find_packages(query) + if len(pkg)>1: + raise "Too many packages to handle" + return pkg[0].get_ebuild_path() # .-------------------------------------------------------. @@ -453,23 +311,12 @@ def output_log(lines, package_ver=""): # `-------------------------------------------------------' def changes(query): - - matches = [] - printed = 0 - - tup = smart_pkgsplit(query) - if tup[0] and tup[1]: - matches = [ tup[0] + "/" + tup[1] ] - elif tup[1]: - matches = search(tup[1]) - - - print "[ Results for search key : " + white(query) + " ]" - #print "[ Applications found : " + white(str(len(matches))) + " ]" - print + matches=gentoolkit.find_packages(query) + if not report_matches(matches,query): + return - for match in matches: - changelog_file = portage.settings["PORTDIR"] + '/' + match + '/ChangeLog' + for pkg in matches: + changelog_file = pkg.get_portage_path() + "/ChangeLog" if os.path.exists(changelog_file): if tup[2] and tup[3]: printed = output_log(open(changelog_file).readlines(),match.split('/')[1] + ".*-" + tup[2] + "-" + tup[3]) or printed @@ -492,18 +339,19 @@ def changes(query): # `-------------------------------------------------------' def versions(query): + tup = smart_pkgsplit(query) if tup[0] and tup[1]: matches = [ tup[0] + "/" + tup[1] ] elif tup[1]: - matches = search(tup[1]) + matches = gentoolkit.find_packages(tup[1]) print "[ Results for search key : " + white(query) + " ]" print "[ Applications found : " + white(str(len(matches))) + " ]" print for package in matches: - print green("*") + " " + white(package) + " :" + print green("*") + " " + white(package.get_cpv()) + " :" versions = portage.portdb.xmatch("match-all", package) unmasked = portage.portdb.xmatch("match-visible",package) curver = portage.db["/"]["vartree"].dep_bestmatch(package) @@ -517,6 +365,7 @@ def versions(query): state = [] color = green unstable = 0 + overlay = "" # check if masked if ver not in unmasked: @@ -547,6 +396,14 @@ def versions(query): color = turquoise else: state.append(" ") + + # check if this is a OVERLAY ebuilds + try: + if portage.portdb.oroot: + if os.path.exists(portage.portdb.oroot + "/" + package + "/" + pkg + ".ebuild"): + overlay = " OVERLAY" + except AttributeError: + pass # print try: @@ -555,8 +412,8 @@ def versions(query): slot = ["0"] except KeyError: slot = ["?"] - - print " "*8 + "[" + string.join(state,"") + "] " + color(ver) + " (" + color(slot[0]) + ")" + + print " "*8 + "[" + string.join(state,"") + "] " + color(ver) + " (" + color(slot[0]) + ")" + overlay print @@ -571,7 +428,7 @@ def uses(query): if tup[0] and tup[1]: matches = [ tup[0] + "/" + tup[1] ] elif tup[1]: - matches = search(tup[1]) + matches = gentoolkit.find_packages(tup[1]) useflags = portage.config()["USE"].split() usedesc = {} @@ -749,6 +606,7 @@ graphcache = [] def graph(query): print "attempt to graph dependencies" + print red("warning, this is BETA, will probably report the wrong results") rgraph(query, []) # return string of deps that are valid @@ -861,7 +719,9 @@ def depends(query): match_depend = {} match_rdepend = {} - + +# for x in gentoolkit.find_all_packages(): + # get all installed packages for x in os.listdir(portage.root + "var/cache/edb/dep"): # for each category, we just grep for the deps, slowly @@ -920,108 +780,71 @@ def belongs(query): return # .-------------------------------------------------------. -# | Size of a particular package | +# | Size of all packages matching query | # +-------------------------------------------------------+ -# | Finds the size of the installed package | +# | Finds the size of installed packages | # `-------------------------------------------------------' def size(query): - matches = search(query) - # FIXME: use portage.settings - dbdir = "/var/db/pkg/" - + packages = gentoolkit.find_packages(query) + if not report_matches(query, packages): + return + for pkg in packages: + if not pkg.is_installed(): + continue + x=pkg.size() + cpv=x[0] + size=x[1] + files=x[2] + uncounted=x[3] + print turquoise("*") + " " + white(pkg.get_cpv()) + print string.rjust(" Total Files : ",25) + str(files) + if uncounted: + print string.rjust(" Inaccessible Files : ",25) + str(uncounted) + print string.rjust(" Total Size : ",25) + "%.2f KB" % (size/1024.0) + + +def report_matches(query, matches): print "[ Results for search key : " + white(query) + " ]" print "[ Applications found : " + white(str(len(matches))) + " ]" print + if matches: print " Only printing found installed programs." - print - - for package in matches: - files = glob.glob(dbdir + package + "-[0-9]*") - if files: - for pkg in files: - # for each package we find - size = 0 - files = 0 - uncounted = 0 - if os.path.exists(pkg): - try: - f = open(pkg + "/CONTENTS") - except: - # fail silently - continue - for line in f.readlines(): - words = line.split() - if len(words) > 2 and words[0] == "obj": - try: - size = size + os.stat(words[1]).st_size - files = files + 1 - except OSError: - uncounted = uncounted + 1 - print turquoise("*") + " " + white(os.path.basename(pkg)) - print string.rjust(" Total Files : ",25) + str(files) - if uncounted: - print string.rjust(" Inaccessible Files : ",25) + str(uncounted) - print string.rjust(" Total Size : ",25) + "%.2f KB" % (size/1024.0) - + print + return 1 + else: + print "No packages found." + return 0 + + # .-------------------------------------------------------. # | Files in a package | # +-------------------------------------------------------+ # | Lists all the files in a package | # `-------------------------------------------------------' def files(query): - tup = smart_pkgsplit(query) - if tup[0] and tup[1]: - matches = [ tup[0] + "/" + tup[1] ] - elif tup[1]: - matches = search(tup[1]) - - # FIXME: use portage.settings - dbdir = "/var/db/pkg/" - - print "[ Results for search key : " + white(query) + " ]" - print "[ Applications found : " + white(str(len(matches))) + " ]" - print - - if matches: - print " Only printing found installed programs." - print - else: - print "No packages found." - return + + matches = gentoolkit.find_packages(query) + + if not report_matches(query, matches): + return for package in matches: - if tup[2]: - files = glob.glob(dbdir + package + "-" + tup[2]) - else: - files = glob.glob(dbdir + package + "-[0-9]*") - - if files: - for pkg in files: - # for each package we find - size = 0 - files = 0 - uncounted = 0 - if os.path.exists(pkg): - try: - f = open(pkg + "/CONTENTS") - except: - # fail silently - continue - print - print yellow(" * ") + white("/".join(pkg.split("/")[-2:])) - for line in f.readlines(): - words = line.split() - if len(words) < 2: - continue - elif words[0] == "obj": - print words[1] - elif words[0] == "sym": - print turquoise(words[1]) - elif words[0] == "dir": - print blue(words[1]) - else: - print words[1] + if not package.is_installed(): + continue + contents = package.get_contents() + + print yellow(" * ") + white(package.get_cpv()) + for x in contents.keys(): + t = contents[x][0] + if t == "obj": + print x + elif t == "sym": + print turquoise(x) + elif t == "dir": + print blue(x) + else: + print x # .-------------------------------------------------------. # | Help Function | diff --git a/trunk/src/gentool/gentool-bump-revision b/trunk/src/gentool/gentool-bump-revision index 37eebf9..234b83c 100755 --- a/trunk/src/gentool/gentool-bump-revision +++ b/trunk/src/gentool/gentool-bump-revision @@ -1,7 +1,8 @@ -#! /bin/sh -# Copyright (c) 2002, Gentoo Technologies, Inc. -# Author: Karl Trygve Kalleberg +#!/bin/sh +# Copyright 2002-2003 Gentoo Technologies, Inc. +# Distributed under the terms of the GNU General Public License v2 # $Header$ +# Author: Karl Trygve Kalleberg if [ ! -f $HOME/.gentoo/gentool-env ] ; then echo "You must make a $HOME/.gentoo/gentool-env file that contains" @@ -40,6 +41,10 @@ echo "Updating revisions for ebuilds digests" mv ${oldver}.ebuild ${newver}.ebuild mv files/digest-${oldver} files/digest-${newver} +#echo "Removing old revisions from CVS" +#cvs remove -f ${oldver}.ebuild +#cvs remove -f files/digest-${oldver} + echo "Adding new revisions to CVS" cvs add ${newver}.ebuild cvs add files/digest-${newver} diff --git a/trunk/src/gentoolkit/gentoolkit.py b/trunk/src/gentoolkit/gentoolkit.py new file mode 100644 index 0000000..3332120 --- /dev/null +++ b/trunk/src/gentoolkit/gentoolkit.py @@ -0,0 +1,138 @@ +#! /usr/bin/env python2.2 +# +# Copyright 2003 Karl Trygve Kalleberg +# Copyright 2003 Gentoo Technologies, Inc. +# Distributed under the terms of the GNU General Public License v2 +# +# $Header$ +# Author: Karl Trygve Kalleberg +# +# Portions written ripped from etcat, written by Alistair Tse + +__author__ = "Karl Trygve Kalleberg" +__email__ = "karltk@gentoo.org" +__version__ = "0.1.0" +__productname__ = "gentoolkit" +__description__ = "Gentoolkit Common Library" + +import os +import portage +import re + +settings = portage.settings +porttree = portage.db[portage.root]["porttree"] +vartree = portage.db[portage.root]["vartree"] + +# Nomenclature: +# +# CPV - category/package-version + +class Package: + """Package descriptor. Contains convenience functions for querying the + state of a package, its contents, name manipulation, ebuild info and + similar.""" + def __init__(self,cpv): + self._cpv=cpv + self._scpv=portage.catpkgsplit(self._cpv) + self._db=None + def get_name(self): + """Returns base name of package, no category nor version""" + return self._scpv[1] + def get_version(self): + """Returns version of package, with revision number""" + v=self._scpv[2] + if self._scpv[3] != "r0": + v+="-"+self._scpv[3] + return v + def get_category(self): + """Returns category of package""" + return self._scpv[0] + def get_cpv(self): + """Returns full Category/Package-Version string""" + return self._cpv + def get_dependants(self): + """Retrieves a list of CPVs for all packages depending on this one""" + raise "Not implemented!" + def get_compiletime_dependencies(self): + """Returns a list of first-level compile time dependencies for this package""" + raise "Not implemented!" + def get_runtime_dependencies(self): + """Returns a list of first-level run time dependencies for this package""" + raise "Not implemented!" + def is_installed(self): + """Returns true if this package is installed (merged)""" + self._initdb() + return os.path.exists(self._db.getpath()) + def is_masked(self): + """Returns true if this package is masked against installation. Note: We blindly assume that + the package actually exists on disk somewhere.""" + unmasked = portage.portdb.xmatch("match-visible", self.get_category()+"/"+self.get_name()) + return self._cpv not in unmasked + def get_ebuild_path(self): + """Returns the complete path to the .ebuild file""" + return porttree.getname(self._cpv) + def get_package_path(self): + """Returns the path to where the ChangeLog, Manifest, .ebuild files reside""" + p=self.get_ebuild_path() + sp=p.split("/") + if len(sp): + return string.join(sp[:-1],"/") + def get_env_var(self, var): + """Returns one of the predefined env vars DEPEND, RDEPEND, SRC_URI,....""" + return porttree.dbapi.aux_get(self._cpv,[var]) + def get_contents(self): + """Returns the full contents, as a dictionary, on the form + [ '/bin/foo' : [ 'obj', '1052505381', '45ca8b8975d5094cd75bdc61e9933691' ], ... ]""" + self._initdb() + if self.is_installed(): + return self._db.getcontents() + return {} + def compare_version(self,other): + """Compares this package's version to another's CPV; returns -1, 0, 1""" + v1=self._scpv + v2=portage.catpkgsplit(other) + if v1[0] != v2[0] or v1[1] != v2[1]: + return None + return portage.pkgcmp(v1[1:],v2[1:]) + def size(self): + contents = self.get_contents() + size=0 + uncounted = 0 + files=0 + for x in contents: + try: + size += os.stat(x).st_size + files += 1 + except OSError: + uncounted += 1 + return [self.get_cpv(), size, files, uncounted] + + def _initdb(self): + """Internal helper function; loads package information from disk, + when necessary""" + if not self._db: + cat=self.get_category() + pnv=self.get_name()+"-"+self.get_version() + self._db=portage.dblink(cat,pnv,"") +# +# Should we add stuff like size, depends, files, here? +# +# + +def find_packages(search_key): + """Returns a list of Package objects that matched the search key.""" + # FIXME: this one failes if search_key contains version suffix + t=portage.portdb.match(search_key) + return map(lambda x: Package(x), t) + +def find_all_packages(): + """Returns a list of all known packages, installed or not.""" + t=portage.portdb.cp_all() + return map(lambda x: Package(x), t) + +if __name__ == "__main__": + print "This module is for import only" + +# - get dependencies +# - walk dependency tree + diff --git a/trunk/src/pkg-clean/pkg-clean b/trunk/src/pkg-clean/pkg-clean index 355c9f9..c18f1c9 100644 --- a/trunk/src/pkg-clean/pkg-clean +++ b/trunk/src/pkg-clean/pkg-clean @@ -1,7 +1,7 @@ #!/usr/bin/python -# vim: set ts=4 sw=4: -# Copyright 2002 Gentoo Technologies, Inc. -# Distributed under the terms of the GNU General Public License, v2 or later +# Copyright 1999-2003 Gentoo Technologies, Inc. +# Distributed under the terms of the GNU General Public License v2 +# $Header$ # Author: Leo Lipelis # Author: Karl Trygve Kalleberg @@ -92,7 +92,7 @@ for pkg_core in pkg_hash.keys(): if res == 0: (status, unmerge_out) = commands.getstatusoutput( - "ebuild unmerge %s" % (full_path)) + "ebuild %s unmerge" % (full_path)) print unmerge_out time.sleep(2) if status != 0: diff --git a/trunk/src/pkg-size/pkg-size b/trunk/src/pkg-size/pkg-size new file mode 100644 index 0000000..84dd7df --- /dev/null +++ b/trunk/src/pkg-size/pkg-size @@ -0,0 +1,66 @@ +#! /usr/bin/python +# +# $Header$ +# +# Distributed under the terms of the GNU General Public License v2 +# Copyright (c) 2003 Karl Trygve Kalleberg + +import portage +import pprint +import sys +import os + +__author__ = "Karl Trygve Kalleberg" +__email__ = "karltk@gentoo.org" +__version__ = "0.1.0" +__productname__ = "pkg-size" +__description__ = "Portage package size calculator" + +def find(name): + return portage.portdb.match(name) + +def print_size(cpv): + scpv=portage.catpkgsplit(cpv) + cat = scpv[0] + pnv = scpv[1]+"-"+scpv[2] + if scpv[3] != "r0": + pnv +="-"+scpv[3] + db=portage.dblink(cat,pnv,"") + size=0 + uncounted = 0 + if not os.path.exists(db.getpath()): + return + k=db.getcontents() + if not k: + return + for i in k: + try: + size += os.stat(i).st_size + except OSError: + uncounted += 1 + s = cpv + ": " + str(size) + " bytes (" + str((size+512)/1024) + "KB)" + if uncounted > 0: + s += " (" + str(uncounted) + " file(s) not accessible)" + print s + + +def main(): + # parse parameters + if len(sys.argv) < 2: + print "No arguments!" + return + name = sys.argv[1] + candidates = find(name) + if len(candidates) == 0: + print "No candidate packages found!" + return + + for i in candidates: + print_size(i) + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + print "Operation Aborted!" + diff --git a/trunk/src/qpkg/qpkg b/trunk/src/qpkg/qpkg index 1eac75e..cdbe3c7 100644 --- a/trunk/src/qpkg/qpkg +++ b/trunk/src/qpkg/qpkg @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # # qpkg - query portage package system for various information # @@ -62,6 +62,14 @@ do inst=y ;; + -m|--masked) + grepmask="-L" + ;; + + -n|--non-masked) + grepmask="-l" + ;; + -U|--uninstalled) uninst=y ;; @@ -168,6 +176,8 @@ ${BR}Duplicate Locating: ${BR}Package Selection: ${BL}-f, --find-file${NO}${T}finds package that owns file ${BL}-fp, --find-pattern${NO}${T}finds to package that owns file matching ** + ${BL}-m, --masked${NO}${T}Include${YL} only${NO} masked packages + ${BL}-n, --non-masked${NO}${T}Include${YL} only${NO} non-masked packages ${BL}-I, --installed${NO}${T}Include${YL} only${NO} installed packages ${BL}-U, --uninstalled${NO}${T}Include${YL} only${NO} uninstalled packages ${BL}-g, --group${NO}${T}${T}Find by goup (can be combined with other searches) @@ -215,6 +225,13 @@ fi #For the --dups switch only if [ "${dups}" ]; then +if [ "${grepmask}" ]; then + mask=`python -c 'import portage; print portage.settings["ACCEPT_KEYWORDS"];' 2> /dev/null` + echo -e "Currently accepted keywords: ${BL}${mask}${NO}" + echo -e + mask=`echo ${mask} | perl -pe 's/\s+/|/'` +fi + #First dig out the list of packages with duplicates find /var/db/pkg -iname "*${arg}*.ebuild" 2> /dev/null > /tmp/qpkg.lst dups=`cat /tmp/qpkg.lst | cut -f7 -d/ | @@ -279,6 +296,10 @@ if [ "${ffind}" ]; then | xargs grep -l "${arg}" \ | xargs --no-run-if-empty -n 1 dirname` else + # if the user didnt specify a full path assume they + # want to check in the working dir #17331 + [ "${arg:0:1}" != "/" ] && arg="${PWD}/${arg}" + dirs=`ls /var/db/pkg/${group}/*/CONTENTS \ | xargs grep -l " ${arg}\( .*\)*$" \ | xargs --no-run-if-empty -n 1 dirname` @@ -302,6 +323,9 @@ else temp="/var/db/pkg/.*${arg}" ipak=`echo ${ipak}|sed -e "s: :\n:g"|grep ${temp}` fi + if [ -n "${mask}" ]; then + ipak=`echo ${ipak}|xargs -r egrep ${grepmask} "^KEYWORDS=.*[[:space:]\"\'](${mask})[[:space:]\"\']"` + fi fi # not installed packages (yet:-) if [ ! "${inst}" ]; then @@ -312,6 +336,9 @@ else if [ ${arg} ]; then upak=`echo ${upak}|sed -e "s: :\n:g"|grep ${arg}` fi + if [ -n "${mask}" ]; then + upak=`echo ${upak}|xargs -r egrep ${grepmask} "^KEYWORDS=.*[[:space:]\"\'](${mask})[[:space:]\"\']"` + fi fi fi @@ -335,6 +362,11 @@ for p in ${ipak} ${upak} -;do # if we have no passed parameters then # we can skip the extra conditional checks [[ ${params} == 0 ]] && continue; + + if [ "${mask}" ]; then + keywords=`grep KEYWORDS ${p}| cut -d\" -f2` + echo -e "${T}Keywords: ${BL}${keywords}${NO}" + fi if [ ${verb} -gt 1 ];then echo "vvv ${p}" @@ -473,10 +505,10 @@ for p in ${ipak} ${upak} -;do fi done | ( - if [ ! \( "${tcheck}" -o "${mcheck}" -o "${info}" -o "${list}" -o "${query}" -o ${verb} -gt 0 \) ]; then - sed -e "s:-r[0-9]\+$::" -e "s:-[0-9][^-]*$::"|sort -k2|uniq -1 - elif [ ! \( "${tcheck}" -o "${mcheck}" -o "${info}" -o "${list}" -o "${query}" -o ${verb} -lt 2 \) ]; then - sort -k2|uniq -1 + if [ ! \( "${tcheck}" -o "${mcheck}" -o "${info}" -o "${list}" -o "${query}" -o "${mask}" -o ${verb} -gt 0 \) ]; then + sed -e "s:-r[0-9]\+$::" -e "s:-[0-9][^-]*$::"|sort -k2|uniq -f1 + elif [ ! \( "${tcheck}" -o "${mcheck}" -o "${info}" -o "${list}" -o "${query}" -o "${mask}" -o ${verb} -lt 2 \) ]; then + sort -k2|uniq -f1 else cat fi | sed \ diff --git a/trunk/src/qpkg/qpkg.1 b/trunk/src/qpkg/qpkg.1 index a962270..e4164ea 100644 --- a/trunk/src/qpkg/qpkg.1 +++ b/trunk/src/qpkg/qpkg.1 @@ -76,6 +76,8 @@ Short options may not be combined on the command\-line, yet. The operation of some flags has been changed in version 1.6 by the stripping of version numbers from some output to see the version numbers play with \fI\-v\fR and \fI\-vv\fR. .TP When using \fI\-f\fR with \fI\-l\fR or \fI\-\-check.. \-v\fR options, only matching files will be displayed, unless \fI\-v\fR is doubled, (yet more verbose), equivalent to \fI\-vv\fR. +.TP +When using \fI\-q\fR, it is important to note that the querying of deps checks package names only, because qpkg is not advanced enough (nor can it reasonably made so) to check complete deps with versions. Please use \fBdepclean\fR or \fBemerge --dep-clean\fR to more completely check the dependency sanity of your system. .SH "EXAMPLES" .LP .B qpkg \fI\-\-dups\fR print duplicates oldest first diff --git a/trunk/src/revdep-rebuild/revdep-rebuild b/trunk/src/revdep-rebuild/revdep-rebuild index 0b5138d..71e9f4b 100755 --- a/trunk/src/revdep-rebuild/revdep-rebuild +++ b/trunk/src/revdep-rebuild/revdep-rebuild @@ -13,7 +13,7 @@ LD_LIBRARY_MASK="libodbcinst.so libodbc.so libjava.so libjvm.so" # Base of temporary files names. -LIST=~/.reverse-dep-shlib-rebuild +LIST=~/.revdep-rebuild shopt -s nullglob shopt -s expand_aliases diff --git a/trunk/src/revdep-rebuild/revdep-rebuild-1 b/trunk/src/revdep-rebuild/revdep-rebuild-1 new file mode 100755 index 0000000..a33d024 --- /dev/null +++ b/trunk/src/revdep-rebuild/revdep-rebuild-1 @@ -0,0 +1,351 @@ +#! /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 new file mode 100755 index 0000000..0eb326f --- /dev/null +++ b/trunk/src/revdep-rebuild/revdep-rebuild-2 @@ -0,0 +1,369 @@ +#! /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