diff options
Diffstat (limited to 'src')
77 files changed, 0 insertions, 9095 deletions
diff --git a/src/eclean/AUTHORS b/src/eclean/AUTHORS deleted file mode 100644 index 9263cbb..0000000 --- a/src/eclean/AUTHORS +++ /dev/null @@ -1 +0,0 @@ -Thomas de Grenier de Latour (tgl) <degrenier@easyconnect.fr> diff --git a/src/eclean/ChangeLog b/src/eclean/ChangeLog deleted file mode 100644 index 36d9a28..0000000 --- a/src/eclean/ChangeLog +++ /dev/null @@ -1,27 +0,0 @@ -2005-12-19 Paul Varner <fuzzyray@gentoo.org> - * Add support for reqular expression matching for file names in the - exclude files. - -2005-08-28 Thomas de Grenier de Latour (tgl) <degrenier@easyconnect.fr> - * Version 0.4.1 - * added support for some "eclean-dist" and "eclean-pkg" symlinks on eclean - (and thus refactored command-line parsing and help screen code) - * accept file names in exclude files for specific distfiles protection - (useful to protect the OOo i18n files for instance, which are not in - $SRC_URI but put there manually) - * minor rewrite of some findDistfiles() code - * added /usr/lib/portage/pym python path, just to be sure it comes first - (after all, "ouput" is a pretty generic name for a python module...) - * updated manpage - -2005-08-27 Thomas de Grenier de Latour (tgl) <degrenier@easyconnect.fr> - * Version 0.4 - * added exclusion files support - * added time limit option - * added size limit option (for distfiles only) - * added fetch-restricted distfile optionnal protection - * added --package-names option for protection of all versions of installed - packages. - * removed support of multiple actions on command-line. That would have been - hell with action-specific options. - * updated manpage diff --git a/src/eclean/Makefile b/src/eclean/Makefile deleted file mode 100644 index 79c5895..0000000 --- a/src/eclean/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright 2004 Karl Trygve Kalleberg <karltk@gentoo.org> -# Copyright 2004 Gentoo Technologies, Inc. -# Distributed under the terms of the GNU General Public License v2 -# -# $Header$ - -include ../../makedefs.mak - -all: - -dist: - mkdir -p ../../$(distdir)/src/eclean - cp eclean eclean.1 Makefile *.exclude ../../$(distdir)/src/eclean - cp AUTHORS THANKS TODO ChangeLog ../../$(distdir)/src/eclean - -install: - install -m 0755 eclean $(bindir)/ - ln -sf eclean $(bindir)/eclean-pkg - ln -sf eclean $(bindir)/eclean-dist - install -d $(sysconfdir)/eclean - install -m 0644 distfiles.exclude packages.exclude $(sysconfdir)/eclean/ - install -d $(docdir)/eclean - install -m 0644 AUTHORS THANKS TODO ChangeLog $(docdir)/eclean/ - install -m 0644 eclean.1 $(mandir)/ diff --git a/src/eclean/THANKS b/src/eclean/THANKS deleted file mode 100644 index 6b8dc2e..0000000 --- a/src/eclean/THANKS +++ /dev/null @@ -1,7 +0,0 @@ -The starting point ideas were found here: -http://forums.gentoo.org/viewtopic.php?t=3011 - -Thanks to eswanson and far for their contributions, and to wolf31o2 for his -support. Thanks also to karltk, some of this code was at some point inspired -by his "equery" tool. And thanks to people who had a look on bug #33877: -Benjamin Braatz, fuzzyray, genone, etc. diff --git a/src/eclean/TODO b/src/eclean/TODO deleted file mode 100644 index 04e64ca..0000000 --- a/src/eclean/TODO +++ /dev/null @@ -1,16 +0,0 @@ -- exclusion file syntax could be improved (maybe it should support real - dep-atoms, or wildcards, etc.) - -- some policy to keep the X latest versions of a package (in each of its - SLOT maybe) would be really cool... - -- add an option to protect system binary packages - => yup, but later... (needs some portage modifications to be done right) - -- add actions for PORT_LOGDIR and/or /var/tmp/portage cleaning? - => bah, don't know... imho tmpreaper or find+rm onliners are enough here - -- cleanup of DISTDIR/cvs-src when action=distfiles - => i never use cvs ebuilds, i should check what it does exactly - -- rewrite for a decent Portage API if there ever is one diff --git a/src/eclean/distfiles.exclude b/src/eclean/distfiles.exclude deleted file mode 100644 index a31be55..0000000 --- a/src/eclean/distfiles.exclude +++ /dev/null @@ -1,5 +0,0 @@ -# /etc/eclean/distfiles.exclude -# In this file you can list some categories or cat/pkg-name for which you want -# to protect distfiles from "ecleaning". You can also name some specific files. -# See `man eclean` for syntax details. -metadata.dtd diff --git a/src/eclean/eclean b/src/eclean/eclean deleted file mode 100644 index 55cc2a7..0000000 --- a/src/eclean/eclean +++ /dev/null @@ -1,838 +0,0 @@ -#!/usr/bin/python -# Copyright 2003-2005 Gentoo Foundation -# Distributed under the terms of the GNU General Public License v2 -# $Header: $ - -from __future__ import with_statement - -############################################################################### -# Meta: -__author__ = "Thomas de Grenier de Latour (tgl)" -__email__ = "degrenier@easyconnect.fr" -__version__ = "0.4.1" -__productname__ = "eclean" -__description__ = "A cleaning tool for Gentoo distfiles and binaries." - - -############################################################################### -# Python imports: - -import sys -import os, stat -import re -import time -import getopt -import fpformat -import signal -try: - import portage -except ImportError: - sys.path.insert(0, "/usr/lib/portage/pym") - import portage -try: - from portage.output import * -except ImportError: - from output import * - -listdir = portage.listdir - -############################################################################### -# Misc. shortcuts to some portage stuff: -port_settings = portage.settings -distdir = port_settings["DISTDIR"] -pkgdir = port_settings["PKGDIR"] - -############################################################################### -# printVersion: -def printVersion(): - print "%s (version %s) - %s" \ - % (__productname__, __version__, __description__) - print "Author: %s <%s>" % (__author__,__email__) - print "Copyright 2003-2005 Gentoo Foundation" - print "Distributed under the terms of the GNU General Public License v2" - - -############################################################################### -# printUsage: print help message. May also print partial help to stderr if an -# error from {'options','actions'} is specified. -def printUsage(error=None,help=None): - out = sys.stdout - if error: out = sys.stderr - if not error in ('actions', 'global-options', \ - 'packages-options', 'distfiles-options', \ - 'merged-packages-options', 'merged-distfiles-options', \ - 'time', 'size'): - error = None - if not error and not help: help = 'all' - if error == 'time': - eerror("Wrong time specification") - print >>out, "Time specification should be an integer followed by a"+ \ - " single letter unit." - print >>out, "Available units are: y (years), m (months), w (weeks), "+ \ - "d (days) and h (hours)." - print >>out, "For instance: \"1y\" is \"one year\", \"2w\" is \"two"+ \ - " weeks\", etc. " - return - if error == 'size': - eerror("Wrong size specification") - print >>out, "Size specification should be an integer followed by a"+ \ - " single letter unit." - print >>out, "Available units are: G, M, K and B." - print >>out, "For instance: \"10M\" is \"ten megabytes\", \"200K\" "+ \ - "is \"two hundreds kilobytes\", etc." - return - if error in ('global-options', 'packages-options', 'distfiles-options', \ - 'merged-packages-options', 'merged-distfiles-options',): - eerror("Wrong option on command line.") - print >>out - elif error == 'actions': - eerror("Wrong or missing action name on command line.") - print >>out - print >>out, white("Usage:") - if error in ('actions','global-options', 'packages-options', \ - 'distfiles-options') or help == 'all': - print >>out, " "+turquoise(__productname__), \ - yellow("[global-option] ..."), \ - green("<action>"), \ - yellow("[action-option] ...") - if error == 'merged-distfiles-options' or help in ('all','distfiles'): - print >>out, " "+turquoise(__productname__+'-dist'), \ - yellow("[global-option, distfiles-option] ...") - if error == 'merged-packages-options' or help in ('all','packages'): - print >>out, " "+turquoise(__productname__+'-pkg'), \ - yellow("[global-option, packages-option] ...") - if error in ('global-options', 'actions'): - print >>out, " "+turquoise(__productname__), \ - yellow("[--help, --version]") - if help == 'all': - print >>out, " "+turquoise(__productname__+"(-dist,-pkg)"), \ - yellow("[--help, --version]") - if error == 'merged-packages-options' or help == 'packages': - print >>out, " "+turquoise(__productname__+'-pkg'), \ - yellow("[--help, --version]") - if error == 'merged-distfiles-options' or help == 'distfiles': - print >>out, " "+turquoise(__productname__+'-dist'), \ - yellow("[--help, --version]") - print >>out - if error in ('global-options', 'merged-packages-options', \ - 'merged-distfiles-options') or help: - print >>out, "Available global", yellow("options")+":" - print >>out, yellow(" -C, --nocolor")+ \ - " - turn off colors on output" - print >>out, yellow(" -d, --destructive")+ \ - " - only keep the minimum for a reinstallation" - print >>out, yellow(" -e, --exclude-file=<path>")+ \ - " - path to the exclusion file" - print >>out, yellow(" -i, --interactive")+ \ - " - ask confirmation before deletions" - print >>out, yellow(" -n, --package-names")+ \ - " - protect all versions (when --destructive)" - print >>out, yellow(" -p, --pretend")+ \ - " - only display what would be cleaned" - print >>out, yellow(" -q, --quiet")+ \ - " - be as quiet as possible" - print >>out, yellow(" -t, --time-limit=<time>")+ \ - " - don't delete files modified since "+yellow("<time>") - print >>out, " "+yellow("<time>"), "is a duration: \"1y\" is"+ \ - " \"one year\", \"2w\" is \"two weeks\", etc. " - print >>out, " "+"Units are: y (years), m (months), w (weeks), "+ \ - "d (days) and h (hours)." - print >>out, yellow(" -h, --help")+ \ - " - display the help screen" - print >>out, yellow(" -V, --version")+ \ - " - display version info" - print >>out - if error == 'actions' or help == 'all': - print >>out, "Available", green("actions")+":" - print >>out, green(" packages")+ \ - " - clean outdated binary packages from:" - print >>out, " ",teal(pkgdir) - print >>out, green(" distfiles")+ \ - " - clean outdated packages sources files from:" - print >>out, " ",teal(distdir) - print >>out - if error in ('packages-options','merged-packages-options') \ - or help in ('all','packages'): - print >>out, "Available", yellow("options"),"for the", \ - green("packages"),"action:" - print >>out, yellow(" NONE :)") - print >>out - if error in ('distfiles-options', 'merged-distfiles-options') \ - or help in ('all','distfiles'): - print >>out, "Available", yellow("options"),"for the", \ - green("distfiles"),"action:" - print >>out, yellow(" -f, --fetch-restricted")+ \ - " - protect fetch-restricted files (when --destructive)" - print >>out, yellow(" -s, --size-limit=<size>")+ \ - " - don't delete distfiles bigger than "+yellow("<size>") - print >>out, " "+yellow("<size>"), "is a size specification: "+ \ - "\"10M\" is \"ten megabytes\", \"200K\" is" - print >>out, " "+"\"two hundreds kilobytes\", etc. Units are: "+ \ - "G, M, K and B." - print >>out - print >>out, "More detailed instruction can be found in", \ - turquoise("`man %s`" % __productname__) - - -############################################################################### -# einfo: display an info message depending on a color mode -def einfo(message="", nocolor=False): - if not nocolor: prefix = " "+green('*') - else: prefix = ">>>" - print prefix,message - - -############################################################################### -# eerror: display an error depending on a color mode -def eerror(message="", nocolor=False): - if not nocolor: prefix = " "+red('*') - else: prefix = "!!!" - print >>sys.stderr,prefix,message - - -############################################################################### -# eprompt: display a user question depending on a color mode. -def eprompt(message, nocolor=False): - if not nocolor: prefix = " "+red('>')+" " - else: prefix = "??? " - sys.stdout.write(prefix+message) - sys.stdout.flush() - - -############################################################################### -# prettySize: integer -> byte/kilo/mega/giga converter. Optionnally justify the -# result. Output is a string. -def prettySize(size,justify=False): - units = [" G"," M"," K"," B"] - approx = 0 - while len(units) and size >= 1000: - approx = 1 - size = size / 1024. - units.pop() - sizestr = fpformat.fix(size,approx)+units[-1] - if justify: - sizestr = " " + blue("[ ") + " "*(7-len(sizestr)) \ - + green(sizestr) + blue(" ]") - return sizestr - - -############################################################################### -# yesNoAllPrompt: print a prompt until user answer in yes/no/all. Return a -# boolean for answer, and also may affect the 'accept_all' option. -# Note: i gave up with getch-like functions, to much bugs in case of escape -# sequences. Back to raw_input. -def yesNoAllPrompt(myoptions,message="Do you want to proceed?"): - user_string="xxx" - while not user_string.lower() in ["","y","n","a","yes","no","all"]: - eprompt(message+" [Y/n/a]: ", myoptions['nocolor']) - user_string = raw_input() - if user_string.lower() in ["a","all"]: - myoptions['accept_all'] = True - myanswer = user_string.lower() in ["","y","a","yes","all"] - return myanswer - - -############################################################################### -# ParseArgsException: for parseArgs() -> main() communication -class ParseArgsException(Exception): - def __init__(self, value): - self.value = value - def __str__(self): - return repr(self.value) - - -############################################################################### -# parseSize: convert a file size "Xu" ("X" is an integer, and "u" in [G,M,K,B]) -# into an integer (file size in Bytes). Raises ParseArgsException('size') in -# case of failure. -def parseSize(size): - myunits = { \ - 'G': (1024**3), \ - 'M': (1024**2), \ - 'K': 1024, \ - 'B': 1 \ - } - try: - mymatch = re.match(r"^(?P<value>\d+)(?P<unit>[GMKBgmkb])?$",size) - mysize = int(mymatch.group('value')) - if mymatch.group('unit'): - mysize *= myunits[mymatch.group('unit').capitalize()] - except: - raise ParseArgsException('size') - return mysize - - -############################################################################### -# parseTime: convert a duration "Xu" ("X" is an int, and "u" a time unit in -# [Y,M,W,D,H]) into an integer which is a past EPOCH date. -# Raises ParseArgsException('time') in case of failure. -# (yep, big approximations inside... who cares?) -def parseTime(timespec): - myunits = {'H' : (60 * 60)} - myunits['D'] = myunits['H'] * 24 - myunits['W'] = myunits['D'] * 7 - myunits['M'] = myunits['D'] * 30 - myunits['Y'] = myunits['D'] * 365 - try: - # parse the time specification - mymatch = re.match(r"^(?P<value>\d+)(?P<unit>[YMWDHymwdh])?$",timespec) - myvalue = int(mymatch.group('value')) - if not mymatch.group('unit'): myunit = 'D' - else: myunit = mymatch.group('unit').capitalize() - except: raise ParseArgsException('time') - # calculate the limit EPOCH date - mytime = time.time() - (myvalue * myunits[myunit]) - return mytime - - -############################################################################### -# parseCmdLine: parse the command line arguments. Raise exceptions on errors or -# non-action modes (help/version). Returns an action, and affect the options -# dict. -def parseArgs(myoptions={}): - - # local function for interpreting command line options - # and setting myoptions accordingly - def optionSwitch(myoption,opts,action=None): - return_code = True - for o, a in opts: - if o in ("-h", "--help"): - if action: raise ParseArgsException('help-'+action) - else: raise ParseArgsException('help') - elif o in ("-V", "--version"): - raise ParseArgsException('version') - elif o in ("-C", "--nocolor"): - myoptions['nocolor'] = True - nocolor() - elif o in ("-d", "--destructive"): - myoptions['destructive'] = True - elif o in ("-i", "--interactive") and not myoptions['pretend']: - myoptions['interactive'] = True - elif o in ("-p", "--pretend"): - myoptions['pretend'] = True - myoptions['interactive'] = False - elif o in ("-q", "--quiet"): - myoptions['quiet'] = True - elif o in ("-t", "--time-limit"): - myoptions['time-limit'] = parseTime(a) - elif o in ("-e", "--exclude-file"): - myoptions['exclude-file'] = a - elif o in ("-n", "--package-names"): - myoptions['package-names'] = True - elif o in ("-f", "--fetch-restricted"): - myoptions['fetch-restricted'] = True - elif o in ("-s", "--size-limit"): - myoptions['size-limit'] = parseSize(a) - else: return_code = False - # sanity check of --destructive only options: - for myopt in ('fetch-restricted', 'package-names'): - if (not myoptions['destructive']) and myoptions[myopt]: - if not myoptions['quiet']: - eerror("--%s only makes sense in --destructive mode." \ - % myopt, myoptions['nocolor']) - myoptions[myopt] = False - return return_code - - # here are the different allowed command line options (getopt args) - getopt_options = {'short':{}, 'long':{}} - getopt_options['short']['global'] = "Cdipqe:t:nhV" - getopt_options['long']['global'] = ["nocolor", "destructive", \ - "interactive", "pretend", "quiet", "exclude-file=", "time-limit=", \ - "package-names", "help", "version"] - getopt_options['short']['distfiles'] = "fs:" - getopt_options['long']['distfiles'] = ["fetch-restricted", "size-limit="] - getopt_options['short']['packages'] = "" - getopt_options['long']['packages'] = [""] - # set default options, except 'nocolor', which is set in main() - myoptions['interactive'] = False - myoptions['pretend'] = False - myoptions['quiet'] = False - myoptions['accept_all'] = False - myoptions['destructive'] = False - myoptions['time-limit'] = 0 - myoptions['package-names'] = False - myoptions['fetch-restricted'] = False - myoptions['size-limit'] = 0 - # if called by a well-named symlink, set the acction accordingly: - myaction = None - if os.path.basename(sys.argv[0]) in \ - (__productname__+'-pkg', __productname__+'-packages'): - myaction = 'packages' - elif os.path.basename(sys.argv[0]) in \ - (__productname__+'-dist', __productname__+'-distfiles'): - myaction = 'distfiles' - # prepare for the first getopt - if myaction: - short_opts = getopt_options['short']['global'] \ - + getopt_options['short'][myaction] - long_opts = getopt_options['long']['global'] \ - + getopt_options['long'][myaction] - opts_mode = 'merged-'+myaction - else: - short_opts = getopt_options['short']['global'] - long_opts = getopt_options['long']['global'] - opts_mode = 'global' - # apply getopts to command line, show partial help on failure - try: opts, args = getopt.getopt(sys.argv[1:], short_opts, long_opts) - except: raise ParseArgsException(opts_mode+'-options') - # set myoptions accordingly - optionSwitch(myoptions,opts,action=myaction) - # if action was already set, there should be no more args - if myaction and len(args): raise ParseArgsException(opts_mode+'-options') - # if action was set, there is nothing left to do - if myaction: return myaction - # So, we are in "eclean --foo action --bar" mode. Parse remaining args... - # Only two actions are allowed: 'packages' and 'distfiles'. - if not len(args) or not args[0] in ('packages','distfiles'): - raise ParseArgsException('actions') - myaction = args.pop(0) - # parse the action specific options - try: opts, args = getopt.getopt(args, \ - getopt_options['short'][myaction], \ - getopt_options['long'][myaction]) - except: raise ParseArgsException(myaction+'-options') - # set myoptions again, for action-specific options - optionSwitch(myoptions,opts,action=myaction) - # any remaning args? Then die! - if len(args): raise ParseArgsException(myaction+'-options') - # returns the action. Options dictionary is modified by side-effect. - return myaction - -############################################################################### -# isValidCP: check wether a string is a valid cat/pkg-name -# This is for 2.0.51 vs. CVS HEAD compatibility, i've not found any function -# for that which would exists in both. Weird... -def isValidCP(cp): - if not '/' in cp: return False - try: portage.cpv_getkey(cp+"-0") - except: return False - else: return True - - -############################################################################### -# ParseExcludeFileException: for parseExcludeFile() -> main() communication -class ParseExcludeFileException(Exception): - def __init__(self, value): - self.value = value - def __str__(self): - return repr(self.value) - - -############################################################################### -# parseExcludeFile: parses an exclusion file, returns an exclusion dictionnary -# Raises ParseExcludeFileException in case of fatal error. -def parseExcludeFile(filepath): - excl_dict = { \ - 'categories':{}, \ - 'packages':{}, \ - 'anti-packages':{}, \ - 'garbage':{} } - try: file = open(filepath,"r") - except IOError: - raise ParseExcludeFileException("Could not open exclusion file.") - filecontents = file.readlines() - file.close() - cat_re = re.compile('^(?P<cat>[a-zA-Z0-9]+-[a-zA-Z0-9]+)(/\*)?$') - cp_re = re.compile('^(?P<cp>[-a-zA-Z0-9_]+/[-a-zA-Z0-9_]+)$') - for line in filecontents: - line = line.strip() - if not len(line): continue - if line[0] == '#': continue - try: mycat = cat_re.match(line).group('cat') - except: pass - else: - if not mycat in portage.settings.categories: - raise ParseExcludeFileException("Invalid category: "+mycat) - excl_dict['categories'][mycat] = None - continue - dict_key = 'packages' - if line[0] == '!': - dict_key = 'anti-packages' - line = line[1:] - try: - mycp = cp_re.match(line).group('cp') - if isValidCP(mycp): - excl_dict[dict_key][mycp] = None - continue - else: raise ParseExcludeFileException("Invalid cat/pkg: "+mycp) - except: pass - #raise ParseExcludeFileException("Invalid line: "+line) - try: - excl_dict['garbage'][line] = re.compile(line) - except: - try: - excl_dict['garbage'][line] = re.compile(re.escape(line)) - except: - raise ParseExcludeFileException("Invalid file name/regular expression: "+line) - return excl_dict - - -############################################################################### -# exclDictExpand: returns a dictionary of all CP from porttree which match -# the exclusion dictionary -def exclDictExpand(excl_dict): - mydict = {} - if 'categories' in excl_dict: - # XXX: i smell an access to something which is really out of API... - for mytree in portage.portdb.porttrees: - for mycat in excl_dict['categories']: - for mypkg in listdir(os.path.join(mytree,mycat),ignorecvs=1): - mydict[mycat+'/'+mypkg] = None - if 'packages' in excl_dict: - for mycp in excl_dict['packages']: - mydict[mycp] = None - if 'anti-packages' in excl_dict: - for mycp in excl_dict['anti-packages']: - if mycp in mydict: - del mydict[mycp] - return mydict - - -############################################################################### -# exclDictMatch: checks whether a CP matches the exclusion rules -def exclDictMatch(excl_dict,pkg): - if 'anti-packages' in excl_dict \ - and pkg in excl_dict['anti-packages']: - return False - if 'packages' in excl_dict \ - and pkg in excl_dict['packages']: - return True - mycat = pkg.split('/')[0] - if 'categories' in excl_dict \ - and mycat in excl_dict['categories']: - return True - return False - - -############################################################################### -# findDistfiles: find all obsolete distfiles. -# XXX: what about cvs ebuilds? i should install some to see where it goes... -def findDistfiles( \ - myoptions, \ - exclude_dict={}, \ - destructive=False,\ - fetch_restricted=False, \ - package_names=False, \ - time_limit=0, \ - size_limit=0,): - # this regexp extracts files names from SRC_URI. It is not very precise, - # but we don't care (may return empty strings, etc.), since it is fast. - file_regexp = re.compile('([a-zA-Z0-9_,\.\-\+\~]*)[\s\)]') - clean_dict = {} - keep = [] - pkg_dict = {} - - # create a big CPV->SRC_URI dict of packages whose distfiles should be kept - if (not destructive) or fetch_restricted: - # list all CPV from portree (yeah, that takes time...) - for package in portage.portdb.cp_all(): - for my_cpv in portage.portdb.cp_list(package): - # get SRC_URI and RESTRICT from aux_get - try: (src_uri,restrict) = \ - portage.portdb.aux_get(my_cpv,["SRC_URI","RESTRICT"]) - except KeyError: continue - # keep either all or fetch-restricted only - if (not destructive) or ('fetch' in restrict): - pkg_dict[my_cpv] = src_uri - if destructive: - if not package_names: - # list all CPV from vartree - pkg_list = portage.db[portage.root]["vartree"].dbapi.cpv_all() - else: - # list all CPV from portree for CP in vartree - pkg_list = [] - for package in portage.db[portage.root]["vartree"].dbapi.cp_all(): - pkg_list += portage.portdb.cp_list(package) - for my_cp in exclDictExpand(exclude_dict): - # add packages from the exclude file - pkg_list += portage.portdb.cp_list(my_cp) - for my_cpv in pkg_list: - # skip non-existing CPV (avoids ugly aux_get messages) - if not portage.portdb.cpv_exists(my_cpv): continue - # get SRC_URI from aux_get - try: pkg_dict[my_cpv] = \ - portage.portdb.aux_get(my_cpv,["SRC_URI"])[0] - except KeyError: continue - del pkg_list - - # create a dictionary of files which should be deleted - if not (os.path.isdir(distdir)): - eerror("%s does not appear to be a directory." % distdir, myoptions['nocolor']) - eerror("Please set DISTDIR to a sane value.", myoptions['nocolor']) - eerror("(Check your /etc/make.conf and environment).", myoptions['nocolor']) - exit(1) - for file in os.listdir(distdir): - filepath = os.path.join(distdir, file) - try: file_stat = os.stat(filepath) - except: continue - if not stat.S_ISREG(file_stat[stat.ST_MODE]): continue - if size_limit and (file_stat[stat.ST_SIZE] >= size_limit): - continue - if time_limit and (file_stat[stat.ST_MTIME] >= time_limit): - continue - if 'garbage' in exclude_dict: - # Try to match file name directly - if file in exclude_dict['garbage']: - file_match = True - # See if file matches via regular expression matching - else: - file_match = False - for file_entry in exclude_dict['garbage']: - if exclude_dict['garbage'][file_entry].match(file): - file_match = True - break - - if file_match: - continue - # this is a candidate for cleaning - clean_dict[file]=[filepath] - # remove files owned by some protected packages - for my_cpv in pkg_dict: - for file in file_regexp.findall(pkg_dict[my_cpv]+"\n"): - if file in clean_dict: - del clean_dict[file] - # no need to waste IO time if there is nothing left to clean - if not len(clean_dict): return clean_dict - return clean_dict - - -############################################################################### -# findPackages: find all obsolete binary packages. -# XXX: packages are found only by symlinks. Maybe i should also return .tbz2 -# files from All/ that have no corresponding symlinks. -def findPackages( \ - myoptions, \ - exclude_dict={}, \ - destructive=False, \ - time_limit=0, \ - package_names=False): - clean_dict = {} - # create a full package dictionary - - if not (os.path.isdir(pkgdir)): - eerror("%s does not appear to be a directory." % pkgdir, myoptions['nocolor']) - eerror("Please set PKGDIR to a sane value.", myoptions['nocolor']) - eerror("(Check your /etc/make.conf and environment).", myoptions['nocolor']) - exit(1) - for root, dirs, files in os.walk(pkgdir): - if root[-3:] == 'All': continue - for file in files: - if not file[-5:] == ".tbz2": - # ignore non-tbz2 files - continue - path = os.path.join(root, file) - category = os.path.split(root)[-1] - cpv = category+"/"+file[:-5] - mystat = os.lstat(path) - if time_limit and (mystat[stat.ST_MTIME] >= time_limit): - # time-limit exclusion - continue - # dict is cpv->[files] (2 files in general, because of symlink) - clean_dict[cpv] = [path] - #if os.path.islink(path): - if stat.S_ISLNK(mystat[stat.ST_MODE]): - clean_dict[cpv].append(os.path.realpath(path)) - # keep only obsolete ones - if destructive: - mydbapi = portage.db[portage.root]["vartree"].dbapi - if package_names: cp_all = dict.fromkeys(mydbapi.cp_all()) - else: cp_all = {} - else: - mydbapi = portage.db[portage.root]["porttree"].dbapi - cp_all = {} - for mycpv in clean_dict.keys(): - if exclDictMatch(exclude_dict,portage.cpv_getkey(mycpv)): - # exclusion because of the exclude file - del clean_dict[mycpv] - continue - if mydbapi.cpv_exists(mycpv): - # exclusion because pkg still exists (in porttree or vartree) - del clean_dict[mycpv] - continue - if portage.cpv_getkey(mycpv) in cp_all: - # exlusion because of --package-names - del clean_dict[mycpv] - - return clean_dict - - -############################################################################### -# doCleanup: takes a dictionnary {'display name':[list of files]}. Calculate -# size of each entry for display, prompt user if needed, delete files if needed -# and return the total size of files that [have been / would be] deleted. -def doCleanup(clean_dict,action,myoptions): - # define vocabulary of this action - if action == 'distfiles': file_type = 'file' - else: file_type = 'binary package' - # sorting helps reading - clean_keys = clean_dict.keys() - clean_keys.sort() - clean_size = 0 - # clean all entries one by one - for mykey in clean_keys: - key_size = 0 - for file in clean_dict[mykey]: - # get total size for an entry (may be several files, and - # symlinks count zero) - if os.path.islink(file): continue - try: key_size += os.path.getsize(file) - except: eerror("Could not read size of "+file, \ - myoptions['nocolor']) - if not myoptions['quiet']: - # pretty print mode - print prettySize(key_size,True),teal(mykey) - elif myoptions['pretend'] or myoptions['interactive']: - # file list mode - for file in clean_dict[mykey]: print file - #else: actually delete stuff, but don't print anything - if myoptions['pretend']: clean_size += key_size - elif not myoptions['interactive'] \ - or myoptions['accept_all'] \ - or yesNoAllPrompt(myoptions, \ - "Do you want to delete this " \ - + file_type+"?"): - # non-interactive mode or positive answer. - # For each file, try to delete the file and clean it out - # of Packages metadata file - if action == 'packages': - metadata = portage.getbinpkg.PackageIndex() - with open(os.path.join(pkgdir, 'Packages')) as metadata_file: - metadata.read(metadata_file) - for file in clean_dict[mykey]: - # ...get its size... - filesize = 0 - if not os.path.exists(file): continue - if not os.path.islink(file): - try: filesize = os.path.getsize(file) - except: eerror("Could not read size of "\ - +file, myoptions['nocolor']) - # ...and try to delete it. - try: - os.unlink(file) - except: - eerror("Could not delete "+file, \ - myoptions['nocolor']) - # only count size if successfully deleted - else: - clean_size += filesize - if action == 'packages': - metadata.packages[:] = [p for p in metadata.packages if 'CPV' in p and p['CPV'] != file] - - if action == 'packages': - with open(os.path.join(pkgdir, 'Packages'), 'w') as metadata_file: - metadata.write(metadata_file) - - # return total size of deleted or to delete files - return clean_size - - -############################################################################### -# doAction: execute one action, ie display a few message, call the right find* -# function, and then call doCleanup with its result. -def doAction(action,myoptions,exclude_dict={}): - # define vocabulary for the output - if action == 'packages': files_type = "binary packages" - else: files_type = "distfiles" - # find files to delete, depending on the action - if not myoptions['quiet']: - einfo("Building file list for "+action+" cleaning...", \ - myoptions['nocolor']) - if action == 'packages': - clean_dict = findPackages( - myoptions, \ - exclude_dict=exclude_dict, \ - destructive=myoptions['destructive'], \ - package_names=myoptions['package-names'], \ - time_limit=myoptions['time-limit']) - else: - clean_dict = findDistfiles( \ - myoptions, \ - exclude_dict=exclude_dict, \ - destructive=myoptions['destructive'], \ - fetch_restricted=myoptions['fetch-restricted'], \ - package_names=myoptions['package-names'], \ - time_limit=myoptions['time-limit'], \ - size_limit=myoptions['size-limit']) - # actually clean files if something was found - if len(clean_dict.keys()): - # verbose pretend message - if myoptions['pretend'] and not myoptions['quiet']: - einfo("Here are "+files_type+" that would be deleted:", \ - myoptions['nocolor']) - # verbose non-pretend message - elif not myoptions['quiet']: - einfo("Cleaning "+files_type+"...",myoptions['nocolor']) - # do the cleanup, and get size of deleted files - clean_size = doCleanup(clean_dict,action,myoptions) - # vocabulary for final message - if myoptions['pretend']: verb = "would be" - else: verb = "has been" - # display freed space - if not myoptions['quiet']: - einfo("Total space that "+verb+" freed in " \ - + action + " directory: " \ - + red(prettySize(clean_size)), \ - myoptions['nocolor']) - # nothing was found, return - elif not myoptions['quiet']: - einfo("Your "+action+" directory was already clean.", \ - myoptions['nocolor']) - - -############################################################################### -# main: parse command line and execute all actions -def main(): - # set default options - myoptions = {} - myoptions['nocolor'] = port_settings["NOCOLOR"] in ('yes','true') \ - and sys.stdout.isatty() - if myoptions['nocolor']: nocolor() - # parse command line options and actions - try: myaction = parseArgs(myoptions) - # filter exception to know what message to display - except ParseArgsException, e: - if e.value == 'help': - printUsage(help='all') - sys.exit(0) - elif e.value[:5] == 'help-': - printUsage(help=e.value[5:]) - sys.exit(0) - elif e.value == 'version': - printVersion() - sys.exit(0) - else: - printUsage(e.value) - sys.exit(2) - # parse the exclusion file - if not 'exclude-file' in myoptions: - my_exclude_file = "/etc/%s/%s.exclude" % (__productname__ , myaction) - if os.path.isfile(my_exclude_file): - myoptions['exclude-file'] = my_exclude_file - if 'exclude-file' in myoptions: - try: exclude_dict = parseExcludeFile(myoptions['exclude-file']) - except ParseExcludeFileException, e: - eerror(e, myoptions['nocolor']) - eerror("Invalid exclusion file: %s" % myoptions['exclude-file'], \ - myoptions['nocolor']) - eerror("See format of this file in `man %s`" % __productname__, \ - myoptions['nocolor']) - sys.exit(1) - else: exclude_dict={} - # security check for non-pretend mode - if not myoptions['pretend'] and portage.secpass == 0: - eerror("Permission denied: you must be root or belong to the portage group.", \ - myoptions['nocolor']) - sys.exit(1) - # execute action - doAction(myaction, myoptions, exclude_dict=exclude_dict) - - -############################################################################### -# actually call main() if launched as a script -if __name__ == "__main__": - try: main() - except KeyboardInterrupt: - print "Aborted." - sys.exit(130) - sys.exit(0) - diff --git a/src/eclean/eclean.1 b/src/eclean/eclean.1 deleted file mode 100644 index 7d785af..0000000 --- a/src/eclean/eclean.1 +++ /dev/null @@ -1,176 +0,0 @@ -.TH "eclean" "1" "0.4.1" "gentoolkit" -.SH "NAME" -eclean \- A cleaning tool for Gentoo distfiles and binary packages. -.SH "SYNOPSIS" -.LP -.B eclean \fR[\fIglobal\-options\fR] ... <\fIactions\fR> \fR[\fIaction\-options\fR] ... -.LP -.B eclean\-dist \fR[\fIglobal\-options, distfiles\-options\fR] ... -.LP -.B eclean\-pkg \fR[\fIglobal\-options, packages\-options\fR] ... -.LP -.B eclean(-dist,-pkg) \fR[\fI\-\-help, \-\-version\fR] -.SH "DESCRIPTION" -\fBeclean\fP is small tool to remove obsolete portage sources files and binary packages. -Used on a regular basis, it prevents your DISTDIR and PKGDIR directories to -infinitely grow, while not deleting files which may still be useful. -.PP -By default, eclean will protect all distfiles or binary packages corresponding to some -ebuilds available in the Portage tree. This is the safest mode, since it will protect -whatever may still be useful, for instance to downgrade a package without downloading -its sources for the second time, or to reinstall a package you unmerge by mistake -without recompiling it. Sure, it's also a mode in which your DISTDIR and PKGDIR will -stay rather big (although still not growing infinitely). For the 'distfiles', this -mode is also quit slow mode because it requiries some access to the whole Portage tree. -.PP -If you use the \-\-destructive option, eclean will only protect files corresponding to -some currently installed package (taking their exact version into account). It will -save much more space, while still preserving sources files around for minor revision -bumps, and binaries for reinstallation of corrupted packages. But it won't keep files -for less usual operations like downgrading or reinstalling an unmerged package. This -is also the fastest execution mode (big difference for distfiles), and the one used by -most other cleaning scripts around like yacleaner (at least in its version 0.3). -.PP -Somewhere in the middle, adding the \-\-package\-names option when using \-\-destructive -will protect files corresponding to all existing versions of installed packages. It will -allow easy downgrading without recompilation or redownloading in case of trouble, but -won't protect you against package uninstallation. -.PP -In addition to this main modes, some options allow to declare a few special cases file -protection rules: -.IP o -\-\-time-limit is useful to protect files which are more recent than a given amount of time. -.IP o -\-\-size-limit (for distfiles only) is useful if you want to protect files bigger than a given size. -.IP o -\-\-fetch-restricted (for distfiles only) is useful to protect manually downloaded files. -But it's also very slow (again, it's a reading of the whole Portage tree data)... -.IP o -Finally, you can list some categories or package names to protect in exclusion files (see -\fBEXCLUSION FILES\fP below). -.SH "PARAMETERS" -.SS "Global options" -.TP -\fB\-C, \-\-nocolor\fP turn off colors on output -.TP -\fB\-d, \-\-destructive\fP only keep the minimum for a reinstallation -.TP -\fB\-e, \-\-exclude\-file=<path>\fP path to the exclusion file -\fB<path>\fP is the absolute path to the exclusion file you want to use. -When this option is not used, default paths are /etc/eclean/{packages,distfiles}.exclude -(if they exist). Use /dev/null if you have such a file at it standard location and -you want to temporary ignore it. -.TP -\fB\-i, \-\-interactive\fP ask confirmation before deleting -.TP -\fB\-n, \-\-package\-names\fP protect all versions (\-\-destructive only) -.TP -\fB\-p, \-\-pretend\fP only display what would be cleaned -.TP -\fB\-q, \-\-quiet\fP be as quiet as possible, only display errors -.TP -\fB\-t, \-\-time-limit=<time>\fP don't delete files modified since <time> -\fB<time>\fP is an amount of time: "1y" is "one year", "2w" is "two weeks", etc. -.br -Units are: y (years), m (months), w (weeks), d (days) and h (hours). -.TP -\fB\-h, \-\-help\fP display the help screen -.TP -\fB\-V, \-\-version\fP display version informations -.SS "Actions" -.TP -\fBdistfiles\fR -Clean files from /usr/portage/distfiles (or whatever else is your DISTDIR in /etc/make.conf). -This action should be useful to almost any Gentoo user, we all have to big DISTDIRs sometime... -.br -\fBeclean\-dist\fP is a shortcut to call eclean with the "distfiles" action, for simplified -command\-line. -.TP -\fBpackages\fR -Clean files from /usr/portage/packages (or whatever else is your PKGDIR in /etc/make.conf). -This action is in particular useful for people who use the "buildpkg" or "buildsyspkg" -FEATURES flags. -.br -\fBeclean\-pkg\fP is a shortcut to call eclean with the "packages" action, for simplified -command\-line. -.SS "Options for the 'distfiles' action" -.TP -\fB\-f, \-\-fetch-restricted\fP protect fetch-restricted files (\-\-destructive only) -.TP -\fB\-s, \-\-size-limit=<size>\fP don't delete distfiles bigger than <size> -<size> is a size specification: "10M" is "ten megabytes", "200K" is "two hundreds kilobytes", -etc. -.br -Units are: G, M, K and B. -.SS "Options for the 'packages' action" -.TP -There is no specific option for this action. -.SH "EXCLUSION FILES" -Exclusions files are lists of packages names or categories you want to protect -in particular. This may be useful to protect more binary packages for some system -related packages for instance. Syntax is the following: -.IP o -blank lines and lines starting with a "#" (comments) are ignored. -.IP o -only one entry per line is allowed. -.IP o -if a line contains a category name, like "sys\-apps", then all packages from this -category will be protected. "sys\-apps/*" is also allowed for aesthetic reasons, but -that does NOT mean that wildcard are supported in any way for any other usage. -.IP o -if a line contains a package name ("app\-shells/bash"), then this package will be -protected. Versioned atoms like ">=app\-shells/bash\-3" are NOT supported. Also, the -full package name (with category) is mandatory. -.IP o -if a line contains a package name with an exclamation mark in front ("!sys\-apps/portage"), -then this package will be excluded from protection. This is only useful if the category -itself was protected. -.IP o -for distfiles protection, a line can also a filename to protect. This is useful if you have -there some files which are not registered by the ebuilds, like OpenOffice.org i18n files -("helpcontent_33_unix.tgz" for instance). -.LP -By default, if it exists, /etc/eclean/packages.exclude (resp. distfiles.exclude) will be use -when action is "packages" (resp. "distfiles"). This can be overide with the \-\-exclude\-file -option. -.SH "EXAMPLES" -.LP -Clean distfiles only, with per file confirmation prompt: -.br -.B # eclean \-i distfiles -.LP -Check which binary packages could be removed, with a no-color display: -.br -.B # eclean \-Cp packages -.LP -Clean binary packages of uninstalled packages, but keep all versions of installed ones: -.br -.B # eclean-pkg \-d \-n -.LP -Clean all distfiles except for installed packages (exact version), those which -are less than one month old, bigger than 50MB, or fetch-restricted: -.br -.B # eclean-dist \-d \-t1m -s50M -f -.LP -From a crontab, silently clean packages in the safest mode, and then distfiles in destructive -mode but protecting files less than a week old, every sunday at 1am: -.br -.B 0 1 * * sun \ \ eclean \-C \-q packages ; eclean \-C \-q \-d \-t1w distfiles -.".SH "BUGS" -.".TP -."The policy used to decide wether a distfile can be removed or not relies on the SRC_URI variables ."of ebuilds. It means that if an ebuild uses files that are not part of its SRC_URI, eclean will ."probably remove them. This are ebuilds bugs, please report them as such on ."http://bugs.gentoo.org. -.".TP -."In safest mode (default, without the \-\-destructive option), this script can be very slow. There -."is not much to do about it without hacking outside of the portage API. -.SH "SEE ALSO" -.TP -The Gentoo forum thread that gave birth to eclean: -.B http://forums.gentoo.org/viewtopic.php?t=3011 -.TP -The bug report requesting eclean inclusion in gentoolkit: -.B http://bugs.gentoo.org/show_bug.cgi?id=33877 -.TP -Yacleaner, one of the other similar tools: -.B http://blog.tacvbo.net/data/files/yacleaner/ -.SH "AUTHORS" -Thomas de Grenier de Latour (tgl) <degrenier@easyconnect.fr> diff --git a/src/eclean/packages.exclude b/src/eclean/packages.exclude deleted file mode 100644 index 8277155..0000000 --- a/src/eclean/packages.exclude +++ /dev/null @@ -1,4 +0,0 @@ -# /etc/eclean/packages.exclude -# In this file you can list some categories or cat/pkg-name for which you want -# to protect binary packages from "ecleaning". -# See `man eclean` for syntax details. diff --git a/src/epkginfo/Makefile b/src/epkginfo/Makefile deleted file mode 100644 index 6a8de9a..0000000 --- a/src/epkginfo/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright 2007 Gentoo Foundation. -# Distributed under the terms of the GNU General Public License v2 -# -# $Header$ - -include ../../makedefs.mak - -all: - echo "CLIXBY (adj.) Politely rude. Bliskly vague. Firmly uninformative." - -dist: - mkdir -p ../../$(distdir)/src/epkginfo - cp Makefile epkginfo epkginfo.1 ../../$(distdir)/src/epkginfo/ - -install: - install -m 0755 epkginfo $(bindir)/ - install -m 0644 epkginfo.1 $(mandir)/ diff --git a/src/epkginfo/epkginfo b/src/epkginfo/epkginfo deleted file mode 100755 index 637deff..0000000 --- a/src/epkginfo/epkginfo +++ /dev/null @@ -1,210 +0,0 @@ -#!/usr/bin/python -############################################################################## -# $Header: $ -############################################################################## -# Distributed under the terms of the GNU General Public License, v2 or later -# Author: Ned Ludd <solar@gentoo.org> (glue all the parts together) -# Author: Eldad Zack <eldad@gentoo.org> (earch) -# Author : Eric Olinger <EvvL AT RustedHalo DOT net> (metadata) - -# Gentoo metadata xml and arch keyword checking tool. - -import os -import sys -try: - import portage -except ImportError: - sys.path.insert(0, "/usr/lib/portage/pym") - import portage -import re -from stat import * -try: - from portage.output import * -except ImportError: - from output import * -from xml.sax import saxutils, make_parser, handler -from xml.sax.handler import feature_namespaces - -version="0.4.1" - -def getvar(pkg, var): - file = open(pkg + ".ebuild") - for line in file.readlines(): - line = line.rstrip() - if re.match("^"+var+"=",line): - vars = re.split("\"",line)[1] - file.close - return re.split(" ",vars) - file.close - -def earch(workdir): - """Prints arch keywords for a given dir""" - portdir = portage.settings["PORTDIR"] - #workdir = "." - os.chdir(workdir) - - archdict = {} - ebuildlist = [] - for file in os.listdir(workdir): - if re.search("\.ebuild$",file): - ebuildlist.append(re.split("\.ebuild$",file)[0]) - - ebuildlist.sort(lambda x,y: portage.pkgcmp(portage.pkgsplit(x),portage.pkgsplit(y))) - - for pkg in ebuildlist: - keywords = getvar(pkg, "KEYWORDS") - for arch in keywords: - if arch == "": - arch = None - archdict[arch] = pkg - - archlist = archdict.keys(); - archlist.sort() - - for pkg in ebuildlist: - print darkgreen("Keywords: ") + pkg + ":", - for value in archlist: - if (value and archdict[value] == pkg): - if value[0] == "-": - print red(value), - elif "~" == value[0]: - print blue(value), - else: - print green(value), - print "" - - -class Metadata_XML(handler.ContentHandler): - _inside_herd="No" - _inside_maintainer="No" - _inside_email="No" - _inside_longdescription="No" - - _herd = "" - _maintainers = [] - _longdescription = "" - - def startElement(self, tag, attr): - if tag == "herd": - self._inside_herd="Yes" - if tag == "longdescription": - self._inside_longdescription="Yes" - if tag == "maintainer": - self._inside_maintainer="Yes" - if tag == "email": - self._inside_email="Yes" - - def endElement(self, tag): - if tag == "herd": - self._inside_herd="No" - if tag == "longdescription": - self._inside_longdescription="No" - if tag == "maintainer": - self._inside_maintainer="No" - if tag == "email": - self._inside_email="No" - - def characters(self, contents): - if self._inside_herd == "Yes": - self._herd = contents - - if self._inside_longdescription == "Yes": - self._longdescription = contents - - if self._inside_maintainer=="Yes" and self._inside_email=="Yes": - self._maintainers.append(contents) - - -def check_metadata(full_package): - """Checks that the primary maintainer is still an active dev and list the hed the package belongs to""" - metadata_file=portage.settings["PORTDIR"] + "/" + portage.pkgsplit(full_package)[0] + "/metadata.xml" - if not os.path.exists(metadata_file): - print darkgreen("Maintainer: ") + red("Error (Missing metadata.xml)") - return 1 - - parser = make_parser() - handler = Metadata_XML() - handler._maintainers = [] - parser.setContentHandler(handler) - parser.parse( metadata_file ) - - if len(handler._herd) < 1: - print darkgreen("Herd: ") + red("Error (No Herd)") - return 1 - else: - print darkgreen("Herd: ") + handler._herd - - if len(handler._maintainers) < 1: - print darkgreen("Maintainer: ") + handler._herd - else: - print darkgreen("Maintainer: ") + ", ".join(handler._maintainers) - - if len(handler._longdescription) > 1: - print darkgreen("Description: ") + handler._longdescription - print darkgreen("Location: ") + os.path.normpath(portage.settings["PORTDIR"] + "/" + portage.pkgsplit(full_package)[0]) - - -def usage(code): - """Prints the uage information for this script""" - print green("epkginfo v" + version + "\n") - print "Usage: epkginfo [package-cat/]package" - sys.exit(code) - - -# default color setup -if ( not sys.stdout.isatty() ) or ( portage.settings["NOCOLOR"] in ["yes","true"] ): - nocolor() - -def fc(x,y): - return cmp(y[0], x[0]) - - -def grab_changelog_devs(catpkg): - try: - os.chdir(portage.settings["PORTDIR"] + "/" + catpkg) - foo="" - r=re.compile("<[^@]+@gentoo.org>", re.I) - s="\n".join(portage.grabfile("ChangeLog")) - d={} - for x in r.findall(s): - if x not in d: - d[x] = 0 - d[x] += 1 - - l=[(d[x], x) for x in d.keys()] - #l.sort(lambda x,y: cmp(y[0], x[0])) - l.sort(fc) - for x in l: - p = str(x[0]) +" "+ x[1].lstrip("<").rstrip(">") - foo += p[:p.find("@")]+", " - return foo - except: - raise - -def main (): - if len( sys.argv ) < 2: - usage(1) - - for pkg in sys.argv[1:]: - - if sys.argv[1:][:1] == "-": - print "NOT WORKING?=="+sys.argv[1:] - continue - - try: - package_list = portage.portdb.xmatch("match-all", pkg) - if package_list: - - catpkg = portage.pkgsplit(package_list[0])[0] - - print darkgreen("Package: ") + catpkg - check_metadata(package_list[0]) - earch(portage.settings["PORTDIR"] + "/" + catpkg) - #print darkgreen("ChangeLog: ") + grab_changelog_devs(catpkg) - print "" - except: - print red("Error: "+pkg+"\n") - - -if __name__ == '__main__': - main() diff --git a/src/epkginfo/epkginfo.1 b/src/epkginfo/epkginfo.1 deleted file mode 100644 index cefe602..0000000 --- a/src/epkginfo/epkginfo.1 +++ /dev/null @@ -1,34 +0,0 @@ -.TH "epkginfo" "1" "0.4.1" "Ned Ludd" "gentoolkit" -.SH "NAME" -.LP -epkginfo \- Displays metadata information from packages in portage -.SH "SYNTAX" -.LP -epkginfo [\fIpackage\-cat/\fP]package -.SH "EXAMPLES" -$ epkginfo app\-portage/gentoolkit -.br -\fBPackage:\fR app\-portage/gentoolkit -.br -\fBHerd:\fR tools\-portage -.br -\fBMaintainer:\fR tools\-portage -.br -\fBLocation:\fR /usr/portage/app\-portage/gentoolkit -.br -\fBKeywords:\fR gentoolkit\-0.2.2: -.br -\fBKeywords:\fR gentoolkit\-0.2.3: mips -.br -\fBKeywords:\fR gentoolkit\-0.2.3\-r1: ppc ppc64 alpha arm s390 amd64 hppa x86 sparc ia64 m68k sh -.br -\fBKeywords:\fR gentoolkit\-0.2.4_pre3: -.br -\fBKeywords:\fR gentoolkit\-0.2.4_pre4: -.br -\fBKeywords:\fR gentoolkit\-0.2.4_pre5: ~arm ~hppa ~x86 ~m68k ~amd64 ~ppc ~sh ~x86\-fbsd ~ia64 ~alpha ~sparc ~ppc64 ~sparc\-fbsd ~mips ~s390 -.SH "AUTHORS" -.LP -Ned Ludd <solar@gentoo.org> -.SH "BUGS" -Please report any bugs to http://bugs.gentoo.org diff --git a/src/equery/AUTHORS b/src/equery/AUTHORS deleted file mode 100644 index 9935ef7..0000000 --- a/src/equery/AUTHORS +++ /dev/null @@ -1,3 +0,0 @@ -Karl Trygve Kalleberg <karltk@gentoo.org> - * Initial version - diff --git a/src/equery/Makefile b/src/equery/Makefile deleted file mode 100644 index 177427d..0000000 --- a/src/equery/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright 2003 Karl Trygve Kalleberg <karltk@gentoo.org> -# Copyright 2003 Gentoo Technologies, Inc. -# Distributed under the terms of the GNU General Public License v2 -# -# $Header$ - -include ../../makedefs.mak - -all: - echo "YADDLETHORPE (vb.) (Of offended pooves.) To exit huffily from a boutique." - -dist: - mkdir -p ../../$(distdir)/src/equery/ - cp Makefile AUTHORS README TODO equery equery.1 ../../$(distdir)/src/equery/ - -install: - install -m 0755 equery $(bindir)/ - install -d $(docdir)/equery - install -m 0644 README AUTHORS $(docdir)/equery/ - install -m 0644 equery.1 $(mandir)/ diff --git a/src/equery/README b/src/equery/README deleted file mode 100644 index e69de29..0000000 --- a/src/equery/README +++ /dev/null diff --git a/src/equery/TODO b/src/equery/TODO deleted file mode 100644 index 5f38e60..0000000 --- a/src/equery/TODO +++ /dev/null @@ -1,63 +0,0 @@ -- sqlite - - regexp comparisons - - check /var/log/emerge.log for database up-to-dateness - - -------------------------- -- pkgquery language: - Query ::= NewStyle | OldStyle | with OldStyle NewStyle - NewStyle ::= NameVar in /RegExp/ - | VerVar in [ VerExpr ] - | SetVar in [ SetExpr ] - NameVar ::= PC | PN | DESCRIPTION | SRC_URI | HOMEPAGE - - SetVar ::= LICENSE | KEYWORDS | IUSE - VerVar ::= SLOT | PV | DEPEND | RDEPEND - - BinaryOp ::= and | or - UnaryOp ::= not - - VerExpr ::= SingleVer - | VerExpr BinOp VerExpr - | UnaryOp UnaryOp - - SetExpr ::= Element - | Element BinOp Element - | UnaryOp Element - - SingleVer ::= PrefixOp VersionBody ( VersionSuffix )? ( - Revision )? - PrefixOp ::= ! | < | > | <= | >= | = | ~ - VersionBody ::= Number ( . Number )+ ( . * )? - VersionSuffix ::= _ ( pre | beta | alpha | rc ) Number? - | [a-z] - Revision ::= r Number - ------- - - PC in /dev-java/ and - PN in /ant/ and - PV in [ >=1.0 or <=2.3 and =2.0.* ] and - IUSE in [ java or junit ] - - --- - with >=dev-java/ant-1.0* - IUSE in [ java or junit ] and - SLOT in [ >=1.0 ] - - ----------- - -old cruft: - - SingleVer ::= ( Operator )? ( Category / ) PackageName ( - Version )? - Operator ::= = | > | >= | < | <= | ~ | ! - Category ::= PackageName - PackageName ::= NamePart ( - NamePart )+ - NamePart ::= [a-zA-Z+]+ - Version ::= VersionPart ( - VersionPart )+ ( _ VersionSuffix )? ( - Revision )? - VersionSuffix ::= ( pre | rc | beta | alpha ) ( Number ) ? - - old style: >=dev-java/ant-1.0* - - diff --git a/src/equery/equery b/src/equery/equery deleted file mode 100755 index fd8fa4f..0000000 --- a/src/equery/equery +++ /dev/null @@ -1,1865 +0,0 @@ -#!/usr/bin/python -# -# Copyright 2003-2004 Karl Trygve Kalleberg -# Copyright 2003-2004 Gentoo Technologies, Inc. -# Distributed under the terms of the GNU General Public License v2 -# -# $Header$ -# Author: Karl Trygve Kalleberg <karltk@gentoo.org> - -__author__ = "Karl Trygve Kalleberg" -__email__ = "karltk@gentoo.org" -__version__ = "0.1.4" -__productname__ = "equery" -__description__ = "Gentoo Package Query Tool" - -import os -import re -import sys -import time -from glob import glob - -# portage (output module) and gentoolkit need special path modifications -sys.path.insert(0, "/usr/lib/gentoolkit/pym") - -import gentoolkit -try: - import portage -except ImportError: - sys.path.insert(0, "/usr/lib/portage/pym") - import portage - -try: - import portage.checksum as checksum - from portage.util import unique_array -except ImportError: - import portage_checksum as checksum - from portage_util import unique_array - -import gentoolkit.pprinter as pp -from gentoolkit.pprinter import print_info, print_error, print_warn, die - -# Auxiliary functions - -def fileAsStr(name, fdesc, showType=0, showMD5=0, showTimestamp=0): - """ - Return file in fdesc as a filename - @param name: - @param fdesc: - @param showType: - @param showMD5: - @param showTimestamp: - @rtype: string - """ - type = ""; fname = ""; stamp = ""; md5sum = "" - - if fdesc[0] == 'obj': - type = "file" - fname = name - stamp = timestampAsStr(int(fdesc[1])) - md5sum = fdesc[2] - elif fdesc[0] == "dir": - type = "dir" - fname = pp.path(name) - elif fdesc[0] == "sym": - type = "symlink" - stamp = timestampAsStr(int(fdesc[1].replace(")",""))) - tgt = fdesc[2].split()[0] - if Config["piping"]: - fname = name - else: - fname = pp.path_symlink(name + " -> " + tgt) - elif fdesc[0] == "fif": - type = "fifo" - fname = name - elif fdesc[0] == "dev": - type = "device" - fname = name - else: - raise Exception(name + " has unknown type: " + fdesc[0]) - - s = "" - if showType: - s += "%6s " % type - s += fname - if showTimestamp: - s += " " + stamp + " " - if showMD5: - s += " " + md5sum + " " - return s - -def timestampAsStr(timestamp): - return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(timestamp)) - - -class Command: - """ - Abstract root class for all equery commands - """ - def __init__(self): - pass - def shortHelp(self): - """Return a help formatted to fit a single line, approx 70 characters. - Must be overridden in the subclass.""" - return " - not implemented yet" - def longHelp(self): - """Return full, multiline, color-formatted help. - Must be overridden in the subclass.""" - return "help for syntax and options" - def perform(self, args): - """Stub code for performing the command. - Must be overridden in the subclass""" - pass - def parseArgs(self, args): - """Stub code for parsing command line arguments for this command. - Must be overridden in the subclass.""" - pass - - -class CmdListFiles(Command): - """List files owned by a particular package""" - def __init__(self): - self.default_options = { - "showType": 0, - "showTimestamp": 0, - "showMD5": 0, - "tree": 0, - "filter": None - } - - def parseArgs(self,args): - query = "" - need_help = 0 - opts = self.default_options - for x in args: - if x in ["-h", "--help"]: - need_help = 1 - elif x in ["--md5sum"]: - opts["showMD5"] = 1 - elif x in ["--timestamp"]: - opts["showTimestamp"] = 1 - elif x in ["--type"]: - opts["showType"] = 1 - elif x in ["--tree"]: - opts["tree"] = 1 - elif x[:9] == "--filter=": - opts["filter"] = x[9:].split(',') - elif x[0] == "/": - die(2, "The query '" + pp.pkgquery(x) + "' does not appear to be a valid package specification") - elif x[0] == "-": - print_warn("unknown local option %s, ignoring" % x) - else: - query = x - - if need_help or query == "": - print_info(0, self.longHelp()) - sys.exit(-1) - - return (query, opts) - - def filterContents(self, cnt, filter): - if filter in [None,[]]: - return cnt - - mycnt = {} - - for mytype in filter: - # Filter elements by type (as recorded in CONTENTS). - if mytype in ["dir","obj","sym","dev","fif"]: - for mykey in cnt.keys(): - if cnt[mykey][0] == mytype: - mycnt[mykey] = cnt[mykey] - - if "cmd" in filter: - # List files that are in $PATH. - userpath = map(os.path.normpath,os.environ["PATH"].split(os.pathsep)) - for mykey in cnt.keys(): - if cnt[mykey][0] in ['obj','sym'] \ - and os.path.dirname(mykey) in userpath: - mycnt[mykey] = cnt[mykey] - - if "path" in filter: - # List only dirs where some files where actually installed, - # and also skip their subdirs. - mykeys = cnt.keys() - mykeys.sort() - while len(mykeys): - mykey = mykeys.pop(0) - if cnt[mykey][0] == 'dir': - i = 0 - while i < len(mykeys) : - if cnt[mykeys[i]][0] != "dir" \ - and os.path.dirname(mykeys[i]) == mykey: - mycnt[mykey] = cnt[mykey] - break - i += 1 - if i < len(mykeys): - while len(mykeys) \ - and len(mykey+"/") < len(mykeys[0]) \ - and mykey+"/" == mykeys[0][:len(mykey)+1]: - mykeys.pop(0) - - if "conf" in filter: - # List configuration files. - conf_path = gentoolkit.settings["CONFIG_PROTECT"].split() - conf_mask_path = gentoolkit.settings["CONFIG_PROTECT_MASK"].split() - conf_path = map(os.path.normpath, conf_path) - conf_mask_path = map(os.path.normpath, conf_mask_path) - for mykey in cnt.keys(): - is_conffile = False - if cnt[mykey][0] == 'obj': - for conf_dir in conf_path: - if conf_dir+"/" == mykey[:len(conf_dir)+1]: - is_conffile = True - for conf_mask_dir in conf_mask_path: - if conf_mask_dir+"/" == mykey[:len(conf_mask_dir)+1]: - is_conffile = False - break - break - if is_conffile: - mycnt[mykey] = cnt[mykey] - - - for mydoctype in ["doc","man","info"]: - # List only files from /usr/share/{doc,man,info} - mydocpath = "/usr/share/"+mydoctype+"/" - if mydoctype in filter: - for mykey in cnt.keys(): - if cnt[mykey][0] == 'obj' \ - and mykey[:len(mydocpath)] == mydocpath : - mycnt[mykey] = cnt[mykey] - - return mycnt - - def perform(self, args): - - (query, opts) = self.parseArgs(args) - - # Turn off filtering for tree output - if opts["tree"]: - opts["filter"] = None - - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(3, "[ Searching for packages matching " + pp.pkgquery(query) + "... ]") - - pkgs = gentoolkit.find_installed_packages(query, True) - for x in pkgs: - if not x.is_installed(): - continue - - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(1, pp.section("* ") + "Contents of " + pp.cpv(x.get_cpv()) + ":") - - cnt = self.filterContents(x.get_contents(),opts["filter"]) - - filenames = cnt.keys() - filenames.sort() - - last=[] - for name in filenames: - if not opts["tree"]: - print_info(0, fileAsStr(name, - cnt[name], - showType=opts["showType"], - showTimestamp=opts["showTimestamp"], - showMD5=opts["showMD5"])) - else: - c = name.split( "/" )[1:] - if cnt[name][0] == "dir": - if len(last) == 0: - last = c - print pp.path(" /" + c[0]) - continue - numol = 0 - for d in c: - if d in last: - numol = last.index(d) + 1 - continue - last = c - if len(last) == 1: - print pp.path(" " + last[0]) - continue - print pp.path(" " * ( numol * 3 ) + "> " + "/" + last[-1]) - elif cnt[name][0] == "sym": - print pp.path(" " * ( bl * 3 ) + "+ ") + pp.path_symlink(c[-1] + " -> " + cnt[name][2]) - else: - bl = len(last) - print pp.path(" " * ( bl * 3 ) + "+ ") + c[-1] - - def longHelp(self): - return "List files owned by a particular package\n" + \ - "\n" + \ - "Syntax:\n" + \ - " " + pp.command("files") + pp.localoption(" <local-opts> ") + pp.pkgquery("<cat/>packagename<-version>") + "\n" + \ - "\n" + \ - "Note: category and version parts are optional. \n" + \ - "\n" + \ - pp.localoption("<local-opts>") + " is either of: \n" + \ - " " + pp.localoption("--timestamp") + " - append timestamp\n" + \ - " " + pp.localoption("--md5sum") + " - append md5sum\n" + \ - " " + pp.localoption("--type") + " - prepend file type\n" + \ - " " + pp.localoption("--tree") + " - display results in a tree (turns off other options)\n" + \ - " " + pp.localoption("--filter=<rules>") + " - filter output\n" + \ - " " + pp.localoption("<rules>") + " is a comma separated list of elements you want to see:\n" + \ - " " + " " + pp.localoption("dir") + \ - ", " + pp.localoption("obj") + \ - ", " + pp.localoption("sym") + \ - ", " + pp.localoption("dev") + \ - ", " + pp.localoption("fifo") + \ - ", " + pp.localoption("path") + \ - ", " + pp.localoption("conf") + \ - ", " + pp.localoption("cmd") + \ - ", " + pp.localoption("doc") + \ - ", " + pp.localoption("man") + \ - ", " + pp.localoption("info") - - def shortHelp(self): - return pp.localoption("<local-opts> ") + pp.pkgquery("pkgspec") + " - list files owned by " + pp.pkgquery("pkgspec") - - -class CmdListBelongs(Command): - """List all packages owning a particular file""" - def __init__(self): - self.default_opts = { - "category": "*", - "fullRegex": 0, - "earlyOut": 0, - "nameOnly": 0 - } - - def parseArgs(self, args): - - query = [] - need_help = 0 - opts = self.default_opts - skip = 0 - - for i in xrange(len(args)): - - if skip: - skip -= 1 - continue - x = args[i] - - if x in ["-h","--help"]: - need_help = 1 - break - elif x in ["-c", "--category"]: - opts["category"] = args[i+1] - skip = 1 - elif x in ["-e", "--earlyout"]: - opts["earlyOut"] = 1 - elif x in ["-f", "--full-regex"]: - opts["fullRegex"] = 1 - elif x in ["-n", "--name-only"]: - opts["nameOnly"] = 1 - elif x[0] == "-": - print_warn("unknown local option %s, ignoring" % x) - else: - query.append(x) - - if need_help or query == []: - print_info(0, self.longHelp()) - sys.exit(-1) - - return (query, opts) - - def perform(self, args): - (query, opts) = self.parseArgs(args) - - if opts["fullRegex"]: - q = query - else: - # Trim trailing and multiple slashes from query - for i in range(0, len(query)): - query[i] = re.compile('/+').sub('/', query[i]) - query[i] = query[i].rstrip('/') - q = map(lambda x: ((len(x) and x[0] == "/") and "^" or "/") - + re.escape(x) + "$", query) - try: - q = "|".join(q) - rx = re.compile(q) - except: - die(2, "The query '" + pp.regexpquery(q) + "' does not appear to be a valid regular expression") - - # Pick out only selected categories - cat = opts["category"] - filter_fn = None - if cat != "*": - filter_fn = lambda x: x.find(cat+"/")==0 - - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(3, "[ Searching for file(s) " + pp.regexpquery(",".join(query)) + " in " + pp.cpv(cat) + "... ]") - - matches = portage.db["/"]["vartree"].dbapi.cpv_all() - #matches = gentoolkit.find_all_installed_packages(filter_fn) - - found = 0 - - def dumpToPipe(pkg): - mysplit = pkg.split("/") - cnt = portage.dblink(mysplit[0], mysplit[1], "/", gentoolkit.settings).getcontents() - #cnt = pkg.get_contents() - if not cnt: return - for file in cnt.keys(): - if rx.search(file) and (opts["category"] == "*" or portage.catpkgsplit(pkg)[0] == opts["category"]): - if opts["nameOnly"]: - x = portage.catpkgsplit(pkg) - print x[0]+"/"+x[1] - else: - print pkg - return - - class DummyExp: - pass - - def dumpToScreen(pkg): - mysplit = pkg.split("/") - cnt = portage.dblink(mysplit[0], mysplit[1], "/", gentoolkit.settings).getcontents() - #cnt = pkg.get_contents() - if not cnt: return - for file in cnt.keys(): - if rx.search(file) and (opts["category"] == "*" or portage.catpkgsplit(pkg)[0] == opts["category"]): - if opts["nameOnly"]: - x = portage.catpkgsplit(pkg) - s = x[0]+"/"+x[1] - else: - s = pkg - s += " (" + pp.path(fileAsStr(file, cnt[file])) + ")" - print_info(0, s) - if opts["earlyOut"]: - raise DummyExp - - try: - if Config["piping"]: - map(dumpToPipe, matches) - else: - map(dumpToScreen, matches) - except DummyExp: - pass - - def shortHelp(self): - return pp.localoption("<local-opts> ") + pp.path("files...") + " - list all packages owning " + pp.path("files...") - def longHelp(self): - return "List all packages owning a particular set of files" + \ - "\n" + \ - "\n" + \ - pp.emph("Note: ") + "Normally, only one package will own a file. If multiple packages own the same file, it usually consitutes a problem, and should be reported.\n" + \ - "\n" + \ - "Syntax:\n" + \ - " " + pp.command("belongs") + pp.localoption(" <local-opts> ") + pp.path("filename") + \ - "\n" + \ - pp.localoption("<local-opts>") + " is either of: \n" + \ - " " + pp.localoption("-c, --category cat") + " - only search in category " + \ - pp.pkgquery("cat") + "\n" + \ - " " + pp.localoption("-f, --full-regex") + " - supplied query is a regex\n" + \ - " " + pp.localoption("-e, --earlyout") + " - stop when first match is found\n" + \ - " " + pp.localoption("-n, --name-only") + " - don't print the version." - -class CmdDisplayUSEs(Command): - """Advanced report of a package's USE flags""" - def __init__(self): - self.default_opts = { - "allPackages" : False - } - def parseArgs(self, args): - - query = "" - need_help = 0 - opts = self.default_opts - skip = 0 - - for i in xrange(len(args)): - - if skip: - skip -= 1 - continue - x = args[i] - - if x in ["-h","--help"]: - need_help = 1 - break - elif x in ["-a", "--all"]: - opts["allPackages"] = True - elif x[0] == "-": - print_warn("unknown local option %s, ignoring" % x) - else: - query = x - - if need_help or query == "": - print_info(0, self.longHelp()) - sys.exit(-1) - - return (query, opts) - - def perform(self, args): - - (query, opts) = self.parseArgs(args) - - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(3, "[ Searching for packages matching " + pp.pkgquery(query) + "... ]") - - if not opts["allPackages"]: - matches = gentoolkit.find_installed_packages(query, True) - if not matches: - matches = gentoolkit.find_packages(query, False) - if matches: - matches = gentoolkit.sort_package_list(matches) - matches = matches[-1:] - else: - matches = gentoolkit.find_packages(query, True) - - if not matches: - die(3, "No matching packages found for \"" + pp.pkgquery(query) + "\"") - - - useflags = gentoolkit.settings["USE"].split() - usedesc = {} - uselocaldesc = {} - - # Load global USE flag descriptions - try: - fd = open(gentoolkit.settings["PORTDIR"]+"/profiles/use.desc") - usedesc = {} - for line in fd.readlines(): - if line[0] == "#": - continue - fields = line.split(" - ", 1) - if len(fields) == 2: - usedesc[fields[0].strip()] = fields[1].strip() - except IOError: - print_warn(5, "Could not load USE flag descriptions from " + ppath(gentoolkit.settings["PORTDIR"] + "/profiles/use.desc")) - - # TODO: Add USE_EXPANDED variables to usedesc hash -- Bug #238005 - # Pseudo-code: - # for all files in gentoolkit.settings["PORTDIR"]+"/desc/*.desc - # variable name = <filename>_<field1> - # description = <field 2> - for descfile in glob(gentoolkit.settings["PORTDIR"]+"/profiles/desc/*.desc"): - try: - fd = open(descfile) - for line in fd.readlines(): - if line[0] == "#": - continue - fields = [field.strip() for field in line.split(" - ", 1)] - if len(fields) == 2: - usedesc["%s_%s" % (descfile.split("/")[-1][0:-5], fields[0],)] = fields[1] - except IOError: - print_warn(5, "Could not load USE flag descriptions from " + descfile) - - # Load local USE flag descriptions - try: - fd = open(gentoolkit.settings["PORTDIR"]+"/profiles/use.local.desc") - for line in fd.readlines(): - if line[0] == "#": - continue - fields = line.split(" - ", 1) - if len(fields) == 2: - catpkguse = re.search("(.*):(.*)", fields[0]) - if catpkguse: - if not uselocaldesc.has_key(catpkguse.group(1).strip()): - uselocaldesc[catpkguse.group(1).strip()] = {catpkguse.group(2).strip() : fields[1].strip()} - else: - uselocaldesc[catpkguse.group(1).strip()][catpkguse.group(2).strip()] = fields[1].strip() - except IOError: - print_warn(5, "Could not load USE flag descriptions from " + path(gentoolkit.settings["PORTDIR"] + "/profiles/use.local.desc")) - - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(3, "[ Colour Code : " + pp.useflagon("set") + " " + pp.useflagoff("unset") + " ]") - print_info(3, "[ Legend : Left column (U) - USE flags from make.conf ]") - print_info(3, "[ : Right column (I) - USE flags packages was installed with ]") - - # Iterate through matches, printing a report for each package - matches = gentoolkit.sort_package_list(matches) - matches_found = 0 - for p in matches: - - matches_found += 1 - - bestver = p.get_cpv() - iuse = p.get_env_var("IUSE") - - if iuse: - # Fix Bug #91623 by making sure the list of USE flags is unique - # Added sort to make output prettier - usevar = unique_array(iuse.split()) - - # Remove prefixed +/- from flags in IUSE, Bug #232019 - for i in range(len(usevar)): - if usevar[i][0] == "+" or usevar[i][0] == "-": - usevar[i] = usevar[i][1:] - - usevar.sort() - else: - usevar = [] - - inuse = [] - if p.is_installed(): - used = p.get_use_flags().split() - else: - # cosmetic issue here as noninstalled packages don't have "used" flags - used = useflags - - # store (inuse, inused, flag, desc) - output = [] - - for u in usevar: - inuse = 0 - inused = 0 - try: - desc = usedesc[u] - except KeyError: - try: - desc = uselocaldesc[p.get_category() + "/" + p.get_name()][u] - except KeyError: - desc = "" - - if u in p.get_settings("USE").split(): - inuse = 1 - if u in used: - inused = 1 - - output.append((inuse, inused, u, desc)) - - # pretty print - if output: - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(0, "[ Found these USE variables for " + pp.cpv(bestver) + " ]") - print_info(3, pp.emph(" U I")) - maxflag_len = 0 - for inuse, inused, u, desc in output: - if len(u) > maxflag_len: - maxflag_len = len(u) - - for in_makeconf, in_installed, flag, desc in output: - markers = ["-","+"] - colour = [pp.useflagoff, pp.useflagon] - if Config["piping"]: - print_info(0, markers[in_makeconf] + flag) - else: - if in_makeconf != in_installed: - print_info(0, pp.emph(" %s %s" % (markers[in_makeconf], markers[in_installed])), False) - else: - print_info(0, " %s %s" % (markers[in_makeconf], markers[in_installed]), False) - - print_info(0, " " + colour[in_makeconf](flag.ljust(maxflag_len)), False) - - # print description - if desc: - print_info(0, " : " + desc) - else: - print_info(0, " : <unknown>") - else: - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(1, "[ No USE flags found for " + pp.cpv(p.get_cpv()) + "]") - - if Config["verbosityLevel"] >= 2: - if matches_found == 0: - s = "" - die(3, "No " + s + "packages found for " + pp.pkgquery(query)) - - - def shortHelp(self): - return pp.localoption("<local-opts> ") + pp.pkgquery("pkgspec") + " - display USE flags for " + pp.pkgquery("pkgspec") - def longHelp(self): - return "Display USE flags for a given package\n" + \ - "\n" + \ - "Syntax:\n" + \ - " " + pp.command("uses") + pp.localoption(" <local-opts> ") + pp.pkgquery("pkgspec") + \ - "\n" + \ - pp.localoption("<local-opts>") + " is: \n" + \ - " " + pp.localoption("-a, --all") + " - include all package versions\n" - - -class CmdDisplayDepGraph(Command): - """Display tree graph of dependencies for a query""" - - def __init__(self): - self.default_opts = { - "displayUSEFlags": 1, - "fancyFormatting": 1, - "depth": 0 - } - - def parseArgs(self, args): - - query = "" - need_help = 0 - opts = self.default_opts - skip = 0 - - for i in xrange(len(args)): - - if skip: - skip -= 1 - continue - x = args[i] - - if x in ["-h","--help"]: - need_help = 1 - break - elif x in ["-U","--no-useflags"]: - opts["displayUSEFlags"] = 0 - elif x in ["-l","--linear"]: - opts["fancyFormatting"] = 0 - elif x[:8] == "--depth=": - opts["depth"] = int(x[8:]) - elif x[0] == "-": - print_warn("unknown local option %s, ignoring" % x) - else: - query = x - - if need_help or query == "": - print_info(0, self.longHelp()) - sys.exit(-1) - - return (query, opts) - - def perform(self, args): - (query, opts) = self.parseArgs(args) - - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(3, "[ Searching for packages matching " + pp.pkgquery(query) + "... ]") - - matches = gentoolkit.find_packages(query, True) - - for pkg in matches: - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(3, pp.section("* ") + "dependency graph for " + pp.cpv(pkg.get_cpv())) - else: - print_info(0, pkg.get_cpv() + ":") - - stats = { "maxdepth": 0, "packages": 0 } - self._graph(pkg, opts, stats, 0, [], "") - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(0, "[ " + pp.cpv(pkg.get_cpv()) + " stats: packages (" + pp.number(str(stats["packages"])) + \ - "), max depth (" + pp.number(str(stats["maxdepth"])) + ") ]") - - def _graph(self, pkg, opts, stats, level=0, pkgtbl=[], suffix=""): - - stats["packages"] += 1 - stats["maxdepth"] = max(stats["maxdepth"], level) - - cpv = pkg.get_cpv() - - pfx = "" - if opts["fancyFormatting"]: - pfx = level * " " + "`-- " - print_info(0, pfx + cpv + suffix) - - pkgtbl.append(cpv) - - pkgdeps = pkg.get_runtime_deps() + pkg.get_compiletime_deps() + pkg.get_postmerge_deps() - for x in pkgdeps: - suffix = "" - cpv = x[2] - pkg = gentoolkit.find_best_match(x[0] + cpv) - if not pkg: - print pfx + x[0] + cpv + " (unable to resolve to a package / package masked or removed)" - continue - if pkg.get_cpv() in pkgtbl: - continue - if cpv.find("virtual") == 0: - suffix += " (" + pp.cpv(cpv) + ")" - if len(x[1]) and opts["displayUSEFlags"]: - suffix += " [ " + pp.useflagon(' '.join(x[1])) + " ]" - if (level < opts["depth"] or opts["depth"] <= 0): - pkgtbl = self._graph(pkg, opts, stats, level+1, pkgtbl, suffix) - return pkgtbl - - def shortHelp(self): - return pp.localoption("<local-opts> ") + pp.pkgquery("pkgspec") + " - display a dependency tree for " + pp.pkgquery("pkgspec") - def longHelp(self): - return "Display a dependency tree for a given package\n" + \ - "\n" + \ - "Syntax:\n" + \ - " " + pp.command("depgraph") + pp.localoption(" <local-opts> ") + pp.pkgquery("pkgspec") + \ - "\n" + \ - pp.localoption("<local-opts>") + " is either of: \n" + \ - " " + pp.localoption("-U, --no-useflags") + " - do not show USE flags\n" + \ - " " + pp.localoption("-l, --linear") + " - do not use fancy formatting\n" + \ - " " + pp.localoption(" --depth=n") + " - limit dependency graph to specified depth" - - -class CmdDisplaySize(Command): - """Display disk size consumed by a package""" - def __init__(self): - self.default_opts = { - "regex": 0, - "exact": 0, - "reportSizeInBytes": 0 - } - - def parseArgs(self, args): - - query = "" - need_help = 0 - opts = self.default_opts - skip = 0 - - for i in xrange(len(args)): - - if skip: - skip -= 1 - continue - x = args[i] - - if x in ["-h","--help"]: - need_help = 1 - break - elif x in ["-b","--bytes"]: - opts["reportSizeInBytes"] = 1 - elif x in ["-f", "--full-regex"]: - opts["regex"] = 1 - elif x in ["-e", "--exact-name"]: - opts["exact"] = 1 - elif x[0] == "-": - print_warn("unknown local option %s, ignoring" % x) - else: - query = x - -# if need_help or query == "": - if need_help: - print_info(0, self.longHelp()) - sys.exit(-1) - - return (query, opts) - - def perform(self, args): - (query, opts) = self.parseArgs(args) - - rev = "" - name = "" - ver = "" - cat = "" - - if query != "": - (cat, name, ver, rev) = gentoolkit.split_package_name(query) - if rev == "r0": rev = "" - - # replace empty strings with .* and escape regular expression syntax - if query != "": - if not opts["regex"]: - cat, name, ver, rev = [re.sub('^$', ".*", re.escape(x)) for x in cat, name, ver, rev] - else: - cat, name, ver, rev = [re.sub('^$', ".*", x) for x in cat, name, ver, rev] - - try: - if opts["exact"]: - filter_fn = lambda x: re.match(cat+"/"+name, x) - else: - filter_fn = lambda x: re.match(cat+"/.*"+name, x) - matches = gentoolkit.find_all_installed_packages(filter_fn) - except: - die(2, "The query '" + pp.regexpquery(query) + "' does not appear to be a valid regular expression") - else: - cat, name, ver, rev = [re.sub('^$', ".*", x) for x in cat, name, ver, rev] - matches = gentoolkit.find_all_installed_packages() - - matches = gentoolkit.sort_package_list(matches) - - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(3, "[ Searching for packages matching " + pp.pkgquery(query) + "... ]") - - # If no version supplied, fix regular expression - if ver == ".*": ver = "[0-9]+[^-]*" - - if rev != ".*": # revision supplied - ver = ver + "-" + rev - - if opts["exact"]: - rx = re.compile(cat + "/" + name + "-" + ver) - else: - rx = re.compile(cat + "/.*" + name + ".*-" + ver) - - for pkg in matches: - if rx.search(pkg.get_cpv()): - (size, files, uncounted) = pkg.size() - - if Config["piping"]: - print_info(0, pkg.get_cpv() + ": total(" + str(files) + "), inaccessible(" + str(uncounted) + \ - "), size(" + str(size) + ")") - else: - print_info(0, pp.section("* ") + "size of " + pp.cpv(pkg.get_cpv())) - print_info(0, " Total files : ".rjust(25) + pp.number(str(files))) - - if uncounted: - print_info(0, " Inaccessible files : ".rjust(25) + pp.number(str(uncounted))) - - sz = "%.2f KiB" % (size/1024.0) - if opts["reportSizeInBytes"]: - sz = pp.number(str(size)) + " bytes" - - print_info(0, "Total size : ".rjust(25) + pp.number(sz)) - - - def shortHelp(self): - return pp.localoption("<local-opts> ") + pp.pkgquery("pkgspec") + " - print size of files contained in package " + pp.pkgquery("pkgspec") - def longHelp(self): - return "Print size total size of files contained in a given package" + \ - "\n" + \ - "Syntax:\n" + \ - " " + pp.command("size") + pp.localoption(" <local-opts> ") + pp.pkgquery("pkgspec") + \ - "\n" + \ - pp.localoption("<local-opts>") + " is: \n" + \ - " " + pp.localoption("-b, --bytes") + " - report size in bytes\n" \ - " " + pp.localoption("-f, --full-regex") + " - query is a regular expression\n" + \ - " " + pp.localoption("-e, --exact-name") + " - list only those packages that exactly match\n" - -class CmdDisplayChanges(Command): - """Display changes for pkgQuery""" - pass - -class CheckException: - def __init__(self, s): - self.s = s - -class CmdCheckIntegrity(Command): - """Check timestamps and md5sums for files owned by pkgspec""" - def __init__(self): - self.default_opts = { - "showSummary" : 1, - "showGoodFiles" : 0, - "showBadFiles" : 1, - "checkTimestamp" : 1, - "checkMD5sum": 1 - } - - def parseArgs(self, args): - - query = "" - need_help = 0 - opts = self.default_opts - skip = 0 - - for i in xrange(len(args)): - if skip: - skip -= 1 - continue - x = args[i] - - if x in ["-h","--help"]: - need_help = 1 - break - elif x[0] == "-": - print_warn("unknown local option %s, ignoring" % x) - else: - query = x - - if need_help: - print_info(0, self.longHelp()) - sys.exit(-1) - - return (query, opts) - - def getMD5sum(self, file): - return checksum.perform_md5(file, calc_prelink=1) - - def perform(self, args): - (query, opts) = self.parseArgs(args) - - if query == "": - matches=gentoolkit.find_all_installed_packages() - else: - matches = gentoolkit.find_packages(query, True) - - matches = gentoolkit.sort_package_list(matches) - - for pkg in matches: - if not pkg.is_installed(): - continue - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(1, "[ Checking " + pp.cpv(pkg.get_cpv()) + " ]") - else: - print_info(0, pkg.get_cpv() + ":") - - files = pkg.get_contents() - checked_files = 0 - good_files = 0 - for file in files.keys(): - type = files[file][0] - try: - st = os.lstat(file) - if type == "dir": - if not os.path.isdir(file): - raise CheckException(file + " exists, but is not a directory") - elif type == "obj": - mtime = files[file][1] - md5sum = files[file][2] - if opts["checkMD5sum"]: - try: - actual_checksum = self.getMD5sum(file) - except: - raise CheckException("Failed to calculate MD5 sum for " + file) - - if self.getMD5sum(file) != md5sum: - raise CheckException(file + " has incorrect md5sum") - if opts["checkTimestamp"]: - if int(st.st_mtime) != int(mtime): - raise CheckException(file + (" has wrong mtime (is %d, should be %s)" % (st.st_mtime, mtime))) - elif type == "sym": - # FIXME: nastry strippery; portage should have this fixed! - t = files[file][2] - # target = os.path.normpath(t.strip()) - target = t.strip() - if not os.path.islink(file): - raise CheckException(file + " exists, but is not a symlink") - tgt = os.readlink(file) - if tgt != target: - raise CheckException(file + " does not point to " + target) - elif type == "fif": - pass - else: - pp.print_error(file) - pp.print_error(files[file]) - pp.print_error(type) - raise CheckException(file + " has unknown type " + type) - good_files += 1 - except CheckException, (e): - print_error(e.s) - except OSError: - print_error(file + " does not exist") - checked_files += 1 - print_info(0, pp.section(" * ") + pp.number(str(good_files)) + " out of " + pp.number(str(checked_files)) + " files good") - - def shortHelp(self): - return pp.pkgquery("pkgspec") + " - check MD5sums and timestamps of " + pp.pkgquery("pkgspec") + "'s files" - def longHelp(self): - return "Check package's files against recorded MD5 sums and timestamps" + \ - "\n" + \ - "Syntax:\n" + \ - " " + pp.command("check") + pp.pkgquery(" pkgspec") - -class CmdDisplayStatistics(Command): - """Display statistics about installed and uninstalled packages""" - pass - -class CmdWhich(Command): - """Display the filename of the ebuild for a given package - that would be used by Portage with the current configuration.""" - def __init__(self): - self.default_opts = { - "includeMasked": False - } - - def parseArgs(self, args): - - query = "" - need_help = 0 - opts = self.default_opts - skip = 0 - - for i in xrange(len(args)): - - if skip: - skip -= 1 - continue - x = args[i] - - if x in ["-h","--help"]: - need_help = 1 - break - elif x in ["-m", "--include-masked"]: - opts["includeMasked"] = True - elif x[0] == "-": - print_warn("unknown local option %s, ignoring" % x) - else: - query = x - - if need_help or query == "": - print_info(0, self.longHelp()) - sys.exit(-1) - - return (query, opts) - - def perform(self, args): - (query, opts) = self.parseArgs(args) - - matches = gentoolkit.find_packages(query, opts["includeMasked"]) - matches = gentoolkit.sort_package_list(matches) - - if matches: - pkg = matches[-1] - ebuild_path = pkg.get_ebuild_path() - if ebuild_path: - print_info(0, os.path.normpath(ebuild_path)) - else: - print_warn("There are no ebuilds to satisfy %s" % pkg.get_name()) - else: - print_error("No masked or unmasked packages found for " + pp.pkgquery(query)) - - def shortHelp(self): - return pp.pkgquery("pkgspec") + " - print full path to ebuild for package " + pp.pkgquery("pkgspec") - def longHelp(self): - # Not documenting --include-masked at this time, since I'm not sure that it is needed. - FuzzyRay - return "Print full path to ebuild for a given package" + \ - "\n" + \ - "Syntax:\n" + \ - " " + pp.command("which ") + pp.pkgquery("pkgspec") - -class CmdListGLSAs(Command): - """List outstanding GLSAs.""" - pass - -class CmdListDepends(Command): - """List all packages directly or indirectly depending on pkgQuery""" - def __init__(self): - self.default_opts = { - "onlyDirect": 1, - "onlyInstalled": 1, - "spacing": 0, - "depth": -1 - } - # Used to cache and detect looping - self.pkgseen = [] - self.pkglist = [] - self.pkgdeps = {} - self.deppkgs = {} - - def parseArgs(self, args): - - query = "" - need_help = 0 - opts = self.default_opts - skip = 0 - - for i in xrange(len(args)): - if skip: - skip -= 1 - continue - x = args[i] - - if x in ["-h","--help"]: - need_help = 1 - break - elif x in ["-d", "--direct"]: - opts["onlyDirect"] = 1 - elif x in ["-D", "--indirect"]: - opts["onlyDirect"] = 0 - elif x in ["-a", "--all-packages"]: - opts["onlyInstalled"] = 0 - elif x[:10] == "--spacing=": - opts["spacing"] = int(x[10:]) - elif x[:8] == "--depth=": - opts["depth"] = int(x[8:]) - elif x[0] == "-": - print_warn("unknown local option %s, ignoring" % x) - else: - query = x - - if need_help or query == "": - print self.longHelp() - sys.exit(-1) - return (query, opts) - - def perform(self, args): - - (query, opts) = self.parseArgs(args) - - # We call ourself recursively if --indirect specified. spacing is used to control printing the tree. - spacing = opts["spacing"] - - if not Config["piping"] and Config["verbosityLevel"] >= 3 and not spacing: - print_info(3, "[ Searching for packages depending on " + pp.pkgquery(query) + "... ]") - - isdepend = gentoolkit.split_package_name(query) - isdepends = map((lambda x: x.get_cpv()), gentoolkit.find_packages(query)) - if not isdepends: - print_warn("Warning: No packages found matching %s" % query) - - # Cache the list of packages - if not self.pkglist: - if opts["onlyInstalled"]: - packages = gentoolkit.find_all_installed_packages() - else: - packages = gentoolkit.find_all_packages() - - packages = gentoolkit.sort_package_list(packages) - self.pkglist = packages - else: - packages = self.pkglist - - for pkg in packages: - pkgcpv = pkg.get_cpv() - if not pkgcpv in self.pkgdeps: - try: - deps = pkg.get_runtime_deps() + pkg.get_compiletime_deps() + pkg.get_postmerge_deps() - except KeyError, e: - # If the ebuild is not found... - continue - # Remove duplicate deps - deps = unique_array(deps) - self.pkgdeps[pkgcpv] = deps - else: - deps = self.pkgdeps[pkgcpv] - isdep = 0 - for dependency in deps: - # TODO determine if dependency is enabled by USE flag - # Find all packages matching the dependency - depstr = dependency[0]+dependency[2] - if not depstr in self.deppkgs: - try: - depcpvs = map((lambda x: x.get_cpv()), gentoolkit.find_packages(depstr)) - self.deppkgs[depstr] = depcpvs - except KeyError, e: - print_warn("") - print_warn("Package: " + pkgcpv + " contains invalid dependency specification.") - print_warn("Portage error: " + str(e)) - print_warn("") - continue - else: - depcpvs = self.deppkgs[depstr] - for x in depcpvs: - cpvs=gentoolkit.split_package_name(x) - if x in isdepends: - cat_match=1 - name_match=1 - ver_match=1 - else: - cat_match=0 - name_match=0 - ver_match=0 - # Match Category - if not isdepend[0] or cpvs[0] == isdepend[0]: - cat_match=1 - # Match Name - if cpvs[1] == isdepend[1]: - name_match=1 - # Match Version - if not isdepend[2] or ( cpvs[2] == isdepend[2] and (isdepend[3] \ - or isdepend[3] == "r0" or cpvs[3] == isdepend[3])): - ver_match=1 - - if cat_match and ver_match and name_match: - if not isdep: - if dependency[1]: - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print " " * (spacing * 2) + pp.cpv(pkg.get_cpv()), - print "(" + \ - pp.useflag(" & ".join(dependency[1]) + "? ") + \ - pp.pkgquery(dependency[0]+dependency[2]) + ")" - else: - print " " * (spacing * 2) + pkg.get_cpv() - else: - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print " " * (spacing * 2) + pp.cpv(pkg.get_cpv()), - print "(" + pp.pkgquery(dependency[0]+dependency[2]) + ")" - else: - print " " * (spacing * 2) + pkg.get_cpv() - isdep = 1 - elif not Config["piping"] and Config["verbosityLevel"] >= 3: - if dependency[1]: - print " "*len(pkg.get_cpv()) + " " * (spacing * 2) + \ - " (" + pp.useflag("&".join(dependency[1]) + "? ") + \ - pp.pkgquery(dependency[0]+dependency[2]) + ")" - else: - print " "*len(pkg.get_cpv()) + " " * (spacing * 2) + " (" + \ - pp.pkgquery(dependency[0]+dependency[2]) + ")" - - break - - # if --indirect specified, call ourselves again with the dependency - # Do not call, if we have already called ourselves. - if isdep and not opts["onlyDirect"] and pkg.get_cpv() not in self.pkgseen \ - and (spacing < opts["depth"] or opts["depth"] == -1): - self.pkgseen.append(pkg.get_cpv()) - self.perform(['=' + pkg.get_cpv(), '--indirect', '--spacing=' + str(int(opts["spacing"]+1))]) - opts["spacing"] = spacing; - - - def shortHelp(self): - return pp.localoption("<local-opts> ") + pp.pkgquery("pkgspec") + " - list all direct dependencies matching " + \ - pp.pkgquery("pkgspec") - - def longHelp(self): - return "List all direct dependencies matching a query pattern" + \ - "\n" + \ - "Syntax:\n" + \ - " " + pp.command("depends") + pp.localoption(" <local-opts> ") + pp.pkgquery("pkgspec") + \ - "\n" + \ - pp.localoption("<local-opts>") + " is either of: \n" + \ - " " + pp.localoption("-a, --all-packages") + " - search in all available packages (slow)\n" + \ - " " + pp.localoption("-d, --direct") + " - search direct dependencies only (default)\n" + \ - " " + pp.localoption("-D, --indirect") + " - search indirect dependencies (VERY slow)\n" + \ - " " + pp.localoption(" --depth=n") + " - limit indirect dependency tree to specified depth" - - -class CmdListPackages(Command): - """List packages satisfying pkgQuery""" - def __init__(self): - self.default_opts = { - "category": "*", - "includeInstalled": 1, - "includePortTree": 0, - "includeOverlayTree": 0, - "includeMasked": 1, - "regex": 0, - "exact": 0, - "duplicates": 0 - } - - def parseArgs(self, args): - - query = "" - need_help = 0 - opts = self.default_opts - skip = 0 - - for i in xrange(len(args)): - - if skip: - skip -= 1 - continue - x = args[i] - - if x in ["-h","--help"]: - need_help = 1 - break - elif x in ["-i", "--installed"]: - opts["includeInstalled"] = 1 - elif x in ["-I", "--exclude-installed"]: - # If -I is the only option, warn - # (warning located in perform()) - opts["includeInstalled"] = 0 - elif x in ["-p", "--portage-tree"]: - opts["includePortTree"] = 1 - elif x in ["-o", "--overlay-tree"]: - opts["includeOverlayTree"] = 1 - elif x in ["-m", "--exclude-masked"]: - opts["includeMasked"] = 0 - elif x in ["-f", "--full-regex"]: - opts["regex"] = 1 - elif x in ["-e", "--exact-name"]: - opts["exact"] = 1 - elif x in ["-d", "--duplicates"]: - opts["duplicates"] = 1 - elif x[0] == "-": - print_warn("unknown local option %s, ignoring" % x) - else: - query = x - - # Only search installed packages when listing duplicated packages - if opts["duplicates"]: - opts["includeInstalled"] = 1 - opts["includePortTree"] = 0 - opts["includeOverlayTree"] = 0 - - if need_help: - print_info(0, self.longHelp()) - sys.exit(-1) - - return (query, opts) - - def perform(self, args): - (query, opts) = self.parseArgs(args) - - rev = "" - name = "" - ver = "" - cat = "" - - if query != "": - try: (cat, name, ver, rev) = gentoolkit.split_package_name(query) - except ValueError, e: - if str(e) == 'too many values to unpack': - print_error("A pattern to match against package names was expected, ") - warn_msg = "but %s has too many slashes ('/') to match any package." - die (1, warn_msg % query) - else: raise ValueError(e) - if rev == "r0": rev = "" - - package_finder = None - - if opts["includeInstalled"]: - if opts["includePortTree"] or opts["includeOverlayTree"]: - package_finder = gentoolkit.find_all_packages - else: - package_finder = gentoolkit.find_all_installed_packages - elif opts["includePortTree"] or opts["includeOverlayTree"]: - package_finder = gentoolkit.find_all_uninstalled_packages - else: - # -I was specified, and no selection of what packages to list was made - print_warn("With -I you must specify one of -i, -p or -o. Assuming -p") - opts["includePortTree"] = 1 - package_finder = gentoolkit.find_all_uninstalled_packages - - filter_fn = None - - if Config["verbosityLevel"] >= 3: - scat = "'" + cat + "'" - if not cat: - scat = "all categories" - sname = "package '" + name + "'" - if not name: - sname = "all packages" - if not Config["piping"] and Config["verbosityLevel"] >= 3: - print_info(1, "[ Searching for " + pp.cpv(sname) + " in " + pp.cpv(scat) + " among: ]") - - # replace empty strings with .* and escape regular expression syntax - if query != "": - if not opts["regex"]: - cat, name, ver, rev = [re.sub('^$', ".*", re.escape(x)) for x in cat, name, ver, rev] - else: - cat, name, ver, rev = [re.sub('^$', ".*", x) for x in cat, name, ver, rev] - - try: - if opts["exact"]: - filter_fn = lambda x: re.match(cat+"/"+name, x) - else: - filter_fn = lambda x: re.match(cat+"/.*"+name, x) - matches = package_finder(filter_fn) - except: - die(2, "The query '" + pp.regexpquery(query) + "' does not appear to be a valid regular expression") - else: - cat, name, ver, rev = [re.sub('^$', ".*", x) for x in cat, name, ver, rev] - filter_fn = lambda x: True - matches = package_finder(filter_fn) - - # Find duplicate packages - if opts["duplicates"]: - dups = {} - newmatches = [] - for pkg in matches: - mykey = pkg.get_category() + "/" + pkg.get_name() - if dups.has_key(mykey): - dups[mykey].append(pkg) - else: - dups[mykey] = [pkg] - - for mykey in dups.keys(): - if len(dups[mykey]) > 1: - newmatches += dups[mykey] - - matches = newmatches - - matches = gentoolkit.sort_package_list(matches) - - # If no version supplied, fix regular expression - if ver == ".*": ver = "[0-9]+[^-]*" - - if rev != ".*": # revision supplied - ver = ver + "-" + rev - - if opts["exact"]: - rx = re.compile(cat + "/" + name + "-" + ver) - else: - rx = re.compile(cat + "/.*" + name + ".*-" + ver) - - if opts["includeInstalled"]: - self._print_installed(matches, rx) - - if opts["includePortTree"]: - self._print_porttree(matches, rx) - - if opts["includeOverlayTree"]: - self._print_overlay(matches, rx) - - def _get_mask_status(self, pkg): - pkgmask = 0 - if pkg.is_masked(): - # Uncomment to only have package masked files show an 'M' - # maskreasons = portage.getmaskingstatus(pkg.get_cpv()) - # if "package.mask" in maskreasons: - pkgmask = pkgmask + 3 - keywords = pkg.get_env_var("KEYWORDS").split() - if gentoolkit.settings["ARCH"] not in keywords: - if "~" + gentoolkit.settings["ARCH"] in keywords: - pkgmask = pkgmask + 1 - elif "-" + gentoolkit.settings["ARCH"] in keywords or "-*" in keywords: - pkgmask = pkgmask + 2 - return pkgmask - - def _generic_print(self, header, exclude, matches, rx, status): - if Config["verbosityLevel"] >= 3: - print_info(1, header) - - pfxmodes = [ "---", "I--", "-P-", "--O" ] - maskmodes = [ " ", " ~", " -", "M ", "M~", "M-" ] - - for pkg in matches: - if exclude(pkg): - continue - - pkgmask = self._get_mask_status(pkg) - - slot = pkg.get_env_var("SLOT") - - if rx.search(pkg.get_cpv()): - if Config["piping"]: - print_info(0, pkg.get_cpv()) - else: - print_info(0, "[" + pp.installedflag(pfxmodes[status]) + "] [" + pp.maskflag(maskmodes[pkgmask]) + "] " + pp.cpv(pkg.get_cpv()) + " (" + pp.slot(slot) + ")") - - def _print_overlay(self, matches, rx): - self._generic_print( - pp.section(" *") + " overlay tree (" + pp.path(gentoolkit.settings["PORTDIR_OVERLAY"]) + ")", - lambda x: not x.is_overlay(), - matches, rx, 3) - - def _print_porttree(self, matches, rx): - self._generic_print( - pp.section(" *") + " Portage tree (" + pp.path(gentoolkit.settings["PORTDIR"]) + ")", - lambda x: x.is_overlay() or x.is_installed(), - matches, rx, 2) - - def _print_installed(self, matches, rx): - self._generic_print( - pp.section(" *") + " installed packages", - lambda x: not x.is_installed(), - matches, rx, 1) - - def shortHelp(self): - return pp.localoption("<local-opts> ") + pp.pkgquery("pkgspec") + " - list all packages matching " + pp.pkgquery("pkgspec") - def longHelp(self): - return "List all packages matching a query pattern" + \ - "\n" + \ - "Syntax:\n" + \ - " " + pp.command("list") + pp.localoption(" <local-opts> ") + pp.pkgquery("pkgspec") + \ - "\n" + \ - pp.localoption("<local-opts>") + " is either of: \n" + \ - " " + pp.localoption("-i, --installed") + " - search installed packages (default)\n" + \ - " " + pp.localoption("-I, --exclude-installed") + " - do not search installed packages\n" + \ - " " + pp.localoption("-p, --portage-tree") + " - also search in portage tree (" + gentoolkit.settings["PORTDIR"] + ")\n" + \ - " " + pp.localoption("-o, --overlay-tree") + " - also search in overlay tree (" + gentoolkit.settings["PORTDIR_OVERLAY"] + ")\n" + \ - " " + pp.localoption("-f, --full-regex") + " - query is a regular expression\n" + \ - " " + pp.localoption("-e, --exact-name") + " - list only those packages that exactly match\n" + \ - " " + pp.localoption("-d, --duplicates") + " - list only installed duplicate packages\n" - -class CmdFindUSEs(Command): - """Find all packages with a particular USE flag.""" - def __init__(self): - self.default_opts = { - "category": "*", - "includeInstalled": 1, - "includePortTree": 0, - "includeOverlayTree": 0, - "includeMasked": 1, - "regex": 0 - } - - def parseArgs(self, args): - - query = "" - need_help = 0 - opts = self.default_opts - skip = 0 - - for i in xrange(len(args)): - - if skip: - skip -= 1 - continue - x = args[i] - - if x in ["-h","--help"]: - need_help = 1 - break - elif x in ["-i", "--installed"]: - opts["includeInstalled"] = 1 - elif x in ["-I", "--exclude-installed"]: - opts["includeInstalled"] = 0 - elif x in ["-p", "--portage-tree"]: - opts["includePortTree"] = 1 - elif x in ["-o", "--overlay-tree"]: - opts["includeOverlayTree"] = 1 - elif x in ["-m", "--exclude-masked"]: - opts["includeMasked"] = 0 - elif x[0] == "-": - print_warn("unknown local option %s, ignoring" % x) - else: - query = x - - if need_help: - print_info(0, self.longHelp()) - sys.exit(-1) - - return (query, opts) - - def perform(self, args): - (query, opts) = self.parseArgs(args) - - rev = ".*" - name = ".*" - ver = ".*" - cat = ".*" - - package_finder = None - - if opts["includeInstalled"] and (opts["includePortTree"] or opts["includeOverlayTree"]): - package_finder = gentoolkit.find_all_packages - elif opts["includeInstalled"]: - package_finder = gentoolkit.find_all_installed_packages - elif opts["includePortTree"] or opts["includeOverlayTree"]: - package_finder = gentoolkit.find_all_uninstalled_packages - - if not package_finder: - die(2,"You must specify one of -i, -p or -o") - - filter_fn = lambda x: True - - if Config["verbosityLevel"] >= 3: - scat = "'" + cat + "'" - if cat == ".*": - scat = "all categories" - if not Config["piping"]: - print_info(2, "[ Searching for USE flag " + pp.useflag(query) + " in " + pp.cpv(scat) + " among: ]") - if opts["includeInstalled"]: - print_info(1, pp.section(" *") + " installed packages") - if opts["includePortTree"]: - print_info(1, pp.section(" *") + " Portage tree (" + pp.path(gentoolkit.settings["PORTDIR"]) + ")") - if opts["includeOverlayTree"]: - print_info(1, pp.section(" *") + " overlay tree (" + pp.path(gentoolkit.settings["PORTDIR_OVERLAY"]) + ")") - - matches = package_finder(filter_fn) - - rx = re.compile(cat + "/" + name + "-" + ver + "(-" + rev + ")?") - pfxmodes = [ "---", "I--", "-P-", "--O" ] - maskmodes = [ " ", " ~", " -", "M ", "M~", "M-" ] - for pkg in matches: - status = 0 - if pkg.is_installed(): - status = 1 - elif pkg.is_overlay(): - status = 3 - else: - status = 2 - - useflags = pkg.get_env_var("IUSE").split() - useflags = [f.lstrip("+-") for f in useflags] - - if query not in useflags: - continue - - # Determining mask status - pkgmask = 0 - if pkg.is_masked(): - pkgmask = pkgmask + 3 - keywords = pkg.get_env_var("KEYWORDS").split() - if "~"+gentoolkit.settings["ARCH"] in keywords: - pkgmask = pkgmask + 1 - elif "-*" in keywords or "-"+gentoolkit.settings["ARCH"] in keywords: - pkgmask = pkgmask + 2 - - # Determining SLOT value - slot = pkg.get_env_var("SLOT") - - if (status == 1 and opts["includeInstalled"]) or \ - (status == 2 and opts["includePortTree"]) or \ - (status == 3 and opts["includeOverlayTree"]): - if Config["piping"]: - print_info(0, pkg.get_cpv()) - else: - print_info(0, "[" + pp.installedflag(pfxmodes[status]) + "] [" + pp.maskflag(maskmodes[pkgmask]) + "] " + pp.cpv(pkg.get_cpv()) + " (" + pp.slot(slot) + ")") - - def shortHelp(self): - return pp.localoption("<local-opts> ") + pp.pkgquery("useflag") + " - list all packages with " + pp.pkgquery("useflag") - def longHelp(self): - return "List all packages with a particular USE flag" + \ - "\n" + \ - "Syntax:\n" + \ - " " + pp.command("list") + pp.localoption(" <local-opts> ") + pp.pkgquery("useflag") + \ - "\n" + \ - pp.localoption("<local-opts>") + " is either of: \n" + \ - " " + pp.localoption("-i, --installed") + " - search installed packages (default)\n" + \ - " " + pp.localoption("-I, --exclude-installed") + " - do not search installed packages\n" + \ - " " + pp.localoption("-p, --portage-tree") + " - also search in portage tree (" + gentoolkit.settings["PORTDIR"] + ")\n" + \ - " " + pp.localoption("-o, --overlay-tree") + " - also search in overlay tree (" + gentoolkit.settings["PORTDIR_OVERLAY"] + ")\n" - -# -# Command line tokens to commands mapping -# - -Known_commands = { - "list" : CmdListPackages(), - "files" : CmdListFiles(), - "belongs" : CmdListBelongs(), - "depends" : CmdListDepends(), - "hasuse" : CmdFindUSEs(), - "uses" : CmdDisplayUSEs(), - "depgraph" : CmdDisplayDepGraph(), - "changes" : CmdDisplayChanges(), - "size" : CmdDisplaySize(), - "check" : CmdCheckIntegrity(), - "stats" : CmdDisplayStatistics(), - "glsa" : CmdListGLSAs(), - "which": CmdWhich() - } - -# Short command line tokens - -Short_commands = { - "a" : "glsa", - "b" : "belongs", - "c" : "changes", - "d" : "depends", - "f" : "files", - "g" : "depgraph", - "h" : "hasuse", - "k" : "check", - "l" : "list", - "s" : "size", - "t" : "stats", - "u" : "uses", - "w" : "which" -} - -from gentoolkit import Config - -Config = { - # Query will include packages installed on the system - "installedPackages": 1, - # Query will include packages available for installation - "uninstalledPackages": 0, - # Query will include overlay packages (iff uninstalledPackages==1) - "overlayPackages": 1, - # Query will include masked packages (iff uninstalledPackages==1) - "maskedPackages": 0, - # Query will only consider packages in the following categories, empty means all. - "categoryFilter": [], - # Enable color output (-1 = use Portage setting, 0 = force off, 1 = force on) - "color": -1, - # Level of detail on the output - "verbosityLevel": 3, - # Query will display info for multiple SLOTed versions - "considerDuplicates": 1, - # Are we writing to a pipe? - "piping": 0 -} - -def printVersion(): - """Print the version of this tool to the console.""" - print_info(0, __productname__ + "(" + __version__ + ") - " + \ - __description__) - print_info(0, "Author(s): " + __author__) - -def buildReverseMap(m): - r = {} - for x in m.keys(): - r[m[x]] = x - return r - -def printUsage(): - """Print full usage information for this tool to the console.""" - - short_cmds = buildReverseMap(Short_commands); - - print_info(0, pp.emph("Usage: ") + pp.productname(__productname__) + pp.globaloption(" <global-opts> ") + pp.command("command") + pp.localoption(" <local-opts>")) - print_info(0, "where " + pp.globaloption("<global-opts>") + " is one of") - print_info(0, pp.globaloption(" -q, --quiet") + " - minimal output") - print_info(0, pp.globaloption(" -C, --nocolor") + " - turn off colours") - print_info(0, pp.globaloption(" -h, --help") + " - this help screen") - print_info(0, pp.globaloption(" -V, --version") + " - display version info") - print_info(0, pp.globaloption(" -N, --no-pipe") + " - turn off pipe detection") - - print_info(0, "where " + pp.command("command") + "(" + pp.command("short") + ") is one of") - keys = Known_commands.keys() - keys.sort() - for x in keys: - print_info(0, " " + pp.command(x) + "(" + pp.command(short_cmds[x]) + ") " + \ - Known_commands[x].shortHelp()) - print - -def configure(): - """Set up default configuration. - """ - - # Guess colour output - if (Config["color"] == -1 and \ - ((not sys.stdout.isatty()) or (gentoolkit.settings["NOCOLOR"] in ["yes","true"]))): - pp.output.nocolor() - - # Guess piping output - if not sys.stdout.isatty(): - Config["piping"] = True - else: - Config["piping"] = False - - -def parseArgs(args): - """Parse tool-specific arguments. - - Arguments are on the form equery <tool-specific> [command] <command-specific> - - This function will only parse the <tool-specific> bit. - """ - command = None - local_opts = [] - showhelp = 0 - - def expand(x): - if x in Short_commands.keys(): - return Short_commands[x] - return x - - for i in xrange(len(args)): - x = args[i] - if 0: - pass - elif x in ["-h", "--help"]: - showhelp = True - elif x in ["-V", "--version"]: - printVersion() - sys.exit(0) - elif x in ["-C", "--nocolor"]: - Config["color"] = 0 - pp.output.nocolor() - elif x in ["-N", "--no-pipe"]: - Config["piping"] = False - elif x in ["-q","--quiet"]: - Config["verbosityLevel"] = 0 - elif expand(x) in Known_commands.keys(): - command = Known_commands[expand(x)] - local_opts.extend(args[i+1:]) - if showhelp: - local_opts.append("--help") - break - else: - print_warn("unknown global option %s, reusing as local option" % x) - local_opts.append(x) - - if not command and showhelp: - printUsage() - sys.exit(0) - - return (command, local_opts) - -if __name__ == "__main__": - configure() - (cmd, local_opts) = parseArgs(sys.argv[1:]) - if cmd: - try: - cmd.perform(local_opts) - except KeyError, e: - if e and e[0].find("Specific key requires an operator") >= 0: - print_error("Invalid syntax: missing operator") - print_error("If you want only specific versions please use one of") - print_error("the following operators as prefix for the package name:") - print_error(" > >= = <= <") - print_error("Example to only match gcc versions greater or equal 3.2:") - print_error(" >=sys-devel/gcc-3.2") - print_error("") - print_error("Note: The symbols > and < are used for redirection in the shell") - print_error("and must be quoted if either one is used.") - - else: - print_error("Internal portage error, terminating") - if len(e[0]): - print_error(str(e)) - sys.exit(2) - except ValueError, e: - if isinstance(e[0], list): - print_error("Ambiguous package name " + pp.emph("\"" + local_opts[0] + "\"")) - print_error("Please use one of the following long names:") - for p in e[0]: - print_error(" " + str(p)) - else: - print_error("Internal portage error, terminating") - if len(e[0]): - print_error(str(e[0])) - sys.exit(2) - except KeyboardInterrupt: - print_info(0, "Interrupted by user, aborting.") - else: - print_error("No command or unknown command given") - printUsage() - diff --git a/src/equery/equery.1 b/src/equery/equery.1 deleted file mode 100644 index 27b8078..0000000 --- a/src/equery/equery.1 +++ /dev/null @@ -1,278 +0,0 @@ -.TH "equery" "1" "Oct 2005" "gentoolkit" "" -.SH "NAME" -equery \- Gentoo: Package Query Tool -.SH "SYNOPSIS" -.B equery -.I [global\-opts] command [local\-opts] -.PP - -.SH "DESCRIPTION" -equery is a flexible utility which may display various information about -packages, such as the files they own, their USE flags, the md5sum -of each file owned by a given package, and many other things. - -.SH "OPTIONS" -The 'command' is the only mandatory option to equery. Most commands require -a 'pkgspec' option, which is described by <cat/>packagename<\-version>; -namely, the package name is mandatory, while the category and version are -optional. - -[global\-opts] may be one of: - -.B \-q, \-\-quiet -causes minimal output to be emitted -.PP -.B \-C, \-\-nocolor -turns off colours -.PP -.B \-h, \-\-help -displays a help summary -.PP -.B \-V, \-\-version -displays the equery version -.PP -.B \-N, \-\-no\-pipe -turns off pipe detection -.PP - -Only one command will actually be run, at most. The possible commands are: -.TP -.B belongs <local\-opts> file -This command lists all packages owning the specified file. -.br -Note: Normally, only one package will own a file. If multiple packages own the -same file, it usually consitutes a problem, and should be reported (http://bugs.gentoo.org). -.br -.IP -<local\-opts> is either or both of: -.br -.B \-c, \-\-category cat -only search in category cat -.br -.B \-f, \-\-full\-regex -supplied query is a regex -.br -.B \-e, \-\-earlyout -stop when first match found - -.PP -.B check pkgspec -This command checks the files of the specified package against recorded MD5 -sums and timestamps. -.PP -.TP -.B depends <local\-opts> pkgspec -This command displays all dependencies matching pkgspec. -.br -<local\-opts> is either or both of: -.br -.B \-a, \-\-all\-packages -search in all available packages (slow) -.br -.B \-d, \-\-direct -search direct dependencies only (default) -.br -.B \-D, \-\-indirect -search indirect dependencies (very slow) -.br -.B \-\-depth=n -Limit depth of indirect dependency tree to n levels. Setting \-\-depth=0 is the same as not specifing \-\-indirect. -.PP -.TP -.B depgraph <local\-opts> pkgspec -This command display a dependency tree for pkgspec, by default indented to reflect -how dependancies relate to each other. -.br -.IP -<local\-opts> is either or both of: -.br -.B \-U, \-\-no\-useflags -do not show USE flags. -.br -.B \-l, \-\-linear -do not use fancy formatting -.br -.B \-\-depth=n -Limit depth of dependency graph to n levels. -.PP -.TP -.B files <local\-opts> pkgspec -This lists files owned by a particular package, optionally with extra -information specified by <local\-opts> -.br - -<local\-opts> is any combination of: -.br -.B \-\-timestamp -output the timestamp of each file -.br -.B \-\-md5sum -output the md5sum of each file -.br -.B \-\-type -output the type of each file -.br -.B \-\-tree -display results in a tree (turns off all other options) -.br -.B \-\-filter=<rules> -filter output based on files type or path -.br -.B \t<rules> -is a comma separated list of filtering rules. Available rules are: -.br -.B \t\tdir\ -regular directories -.br -.B \t\tobj\ -regular files -.br -.B \t\tsym\ -symbolic links -.br -.B \t\tdev\ -device nodes -.br -.B \t\tfifo -named pipes -.br -.B \t\tpath -shortest paths where some files where installed -.br -.B \t\tconf -configuration files (based on $CONFIG_PROTECT) -.br -.B \t\tcmd\ -user commands (based on $PATH) -.br -.B \t\tdoc\ -documentation files (from /usr/share/doc) -.br -.B \t\tman\ -manpages (from /usr/share/man) -.br -.B \t\tinfo -info pages (from /usr/share/info) -.PP -.TP -.B hasuse <local\-opts> useflag -This command lists packages matching a particular USE flag in a user\-specified combination -of installed packages, packages which are not installed, the portage tree, and -the portage overlay tree. - -<local\-opts> must not include only \-I; -if \-I is used, \-p and/or \-o must be also be present. By default, only installed -packages are searched. \-o searches only the overlay tree [and possibly -installed packages], -.I not -the main portage tree. - -.B \-i, \-\-installed -search installed packages (default) -.br -.B \-I, \-\-exclude\-installed -do not search installed packages -.br -.B \-p, \-\-portage\-tree -also search in portage tree (/usr/portage) -.br -.B \-o, \-\-overlay\-tree -also search in overlay tree (/usr/local/portage) -.PP -.TP -.B list <local\-opts> pkgspec -This command lists packages matching pkgspec in a user\-specified combination -of installed packages, packages which are not installed, the portage tree, and -the portage overlay tree. By default the list command searches for partial name matches. - -<local\-opts> \-I cannot be used by itself; -if \-I is used, \-p and/or \-o must be also be present. By default, only installed -packages are searched. \-o searches only the overlay tree [and possibly -installed packages], -\fInot\fR the main portage tree. - -.B \-i, \-\-installed -search installed packages (default) -.br -.B \-I, \-\-exclude\-installed -do not search installed packages -.br -.B \-p, \-\-portage\-tree -also search in portage tree (/usr/portage) -.br -.B \-o, \-\-overlay\-tree -also search in overlay tree (/usr/local/portage) -.br -.B \-f, \-\-full\-regex -query is a regular expression -.br -.B \-e, \-\-exact\-name -list only those packages that exactly match -.br -.B \-d, \-\-duplicates -only list installed duplicate packages -.br - -\fBOutput:\fR - -.br -The list command searches packages for the name given. If found, the following info will be displayed: the package location between the first square brackets (I for Installed packages, P for Portage, O for Overlay), the possible masks between the second (~ by keyword, - by arch or M hard masked), then the category and complete name and last of all, the slot in which the package is stored. - -\fBExamples:\fR - -equery list zilla \- list all installed versions of packages containing the string 'zilla' - -equery list \-\-exact\-name x11\-libs/gtk+ \- list all installed versions of x11\-libs/gtk+ - -equery list \-\-full\-regex '(mozilla\-firefox|mozilla\-thunderbird)' \- list all installed versions of mozilla\-firefox and mozilla\-thunderbird - -equery list \-\-duplicates \- list all installed slotted packages -.PP -.TP -.B size <local\-opts> pkgspec -This command outputs the number of files in the specified package, as well as -their total size in an appropriate unit. - -The possible values for <local\-opts>, if specified, are: -.br -.B \-b, \-\-bytes -report size in bytes -.br -.B \-f, \-\-full\-regex -query is a regular expression -.br -.B \-e, \-\-exact\-name -list only those packages that exactly match -.PP -.TP -.B uses <local\-opts> pkgspec -display USE flags for pkgspec. - -The only possible value for <local\-opts>, if specified, is: -.br -.B \-a, \-\-all -include all package versions -.PP -.B which pkgspec -print full path to ebuild for package pkgspec -.PP - -.SH "Unimplemented Options" -.PP -.B changes -.PP -.B glsa \fR \- use glsa\-check for the time being. -.PP -.B stats - - - -.SH "BUGS" -Many options aren't implemented. Command\-line parsing could use some work. -.br -Submit bug reports to http://bugs.gentoo.org -.SH "AUTHORS" -equery, original man page: Karl Trygve Kalleberg <karltk@gentoo.org>, 2003. -.br -Massive man page updates: Katerina Barone\-Adesi <katerinab@gmail.com>, 2004. - diff --git a/src/equery/tests/common-functions.sh b/src/equery/tests/common-functions.sh deleted file mode 100644 index f065a0a..0000000 --- a/src/equery/tests/common-functions.sh +++ /dev/null @@ -1,52 +0,0 @@ -#! /bin/bash -# -# Copyright (c) 2004, Karl Trygve Kalleberg <karltk@gentoo.org> -# Copyright (c) 2004, Gentoo Foundation -# -# Licensed under the GNU General Public License, v2 - -function tempfilename() { - fn=$(date "+%s") - if [ ! -f ${fn}.tmp ] ; then - echo ${fn}.tmp - fi -} - -function report_pass() { - printf "%-40s - passed\n" ${1} -} - -function report_failure() { - printf "%-40s - FAILED!\n" ${1} -} - -function assert_samefile() { - diff $2 $3 && report_pass $1 || report_failure $1 -} - -function assert_eq() { - if [ $2 -eq $3 ] ; then - report_pass $1 - else - printf "FAIL: $2 ! -eq $3\n" - report_failure $1 - fi -} - -function assert_ge() { - if [ $2 -ge $3 ] ; then - report_pass $1 - else - printf "FAIL: $2 ! -ge $3\n" - report_failure $1 - fi -} - -function assert_exists() { - if [ -f $2 ] ; then - report_pass $1 - else - printf "FAIL: $2 does not exist\n" - report_failure $1 - fi -}
\ No newline at end of file diff --git a/src/equery/tests/run-all-tests.sh b/src/equery/tests/run-all-tests.sh deleted file mode 100755 index 4fe2dfe..0000000 --- a/src/equery/tests/run-all-tests.sh +++ /dev/null @@ -1,12 +0,0 @@ -#! /bin/bash -# -# Copyright (c) 2004, Karl Trygve Kalleberg <karltk@gentoo.org> -# Copyright (c) 2004, Gentoo Foundation -# -# Licensed under the GNU General Public License, v2 - -. common-functions.sh - -for x in belongs check depends depgraph files help list size uses which ; do - ./test-${x}.sh -done diff --git a/src/equery/tests/test-belongs-help.out b/src/equery/tests/test-belongs-help.out deleted file mode 100644 index 0d2f583..0000000 --- a/src/equery/tests/test-belongs-help.out +++ /dev/null @@ -1,11 +0,0 @@ -List all packages owning a particular set of files - -Note: Normally, only one package will own a file. If multiple packages own the same file, it usually consitutes a problem, and should be reported. - -Syntax: - belongs <local-opts> filename -<local-opts> is either of: - -c, --category cat - only search in category cat - -f, --full-regex - supplied query is a regex - -e, --earlyout - stop when first match is found - diff --git a/src/equery/tests/test-belongs.sh b/src/equery/tests/test-belongs.sh deleted file mode 100755 index bd0eac4..0000000 --- a/src/equery/tests/test-belongs.sh +++ /dev/null @@ -1,24 +0,0 @@ -#! /bin/bash -# -# Copyright (c) 2004, Karl Trygve Kalleberg <karltk@gentoo.org> -# Copyright (c) 2004, Gentoo Foundation -# -# Licensed under the GNU General Public License, v2 - -. common-functions.sh - -tmpfile=$(tempfilename) - -test_belongs() { - equery belongs $(which gcc) > ${tmpfile} - - x=$(grep "gcc-config" ${tmpfile} | wc -l) - - assert_eq ${FUNCNAME} ${x} 1 -} - -# Run tests - -test_belongs - -rm -f ${tmpfile}
\ No newline at end of file diff --git a/src/equery/tests/test-changes-help.out b/src/equery/tests/test-changes-help.out deleted file mode 100644 index e69de29..0000000 --- a/src/equery/tests/test-changes-help.out +++ /dev/null diff --git a/src/equery/tests/test-check-help.out b/src/equery/tests/test-check-help.out deleted file mode 100644 index 1e6afcf..0000000 --- a/src/equery/tests/test-check-help.out +++ /dev/null @@ -1,3 +0,0 @@ -Check package's files against recorded MD5 sums and timestamps -Syntax: - size pkgspec diff --git a/src/equery/tests/test-check.sh b/src/equery/tests/test-check.sh deleted file mode 100755 index 803299f..0000000 --- a/src/equery/tests/test-check.sh +++ /dev/null @@ -1,39 +0,0 @@ -#! /bin/bash -# -# Copyright (c) 2004, Karl Trygve Kalleberg <karltk@gentoo.org> -# Copyright (c) 2004, Gentoo Foundation -# -# Licensed under the GNU General Public License, v2 - -. common-functions.sh - -tmpfile=$(tempfilename) - -test_check() { - equery check gcc > ${tmpfile} - - x=$(grep "sys-devel/gcc" ${tmpfile} | wc -l) - - assert_ge ${FUNCNAME} ${x} 1 - - x=$(egrep "[0-9]+ out of [0-9]+" ${tmpfile} | wc -l) - assert_ge ${FUNCNAME} ${x} 1 -} - -test_check_permissions() { - equery check sudo > ${tmpfile} - - x=$(grep "app-admin/sudo" ${tmpfile} | wc -l) - - assert_ge ${FUNCNAME} ${x} 1 - - x=$(egrep "[0-9]+ out of [0-9]+" ${tmpfile} | wc -l) - assert_ge ${FUNCNAME} ${x} 1 -} - -# Run tests - -test_check -test_check_permissions - -rm -f ${tmpfile} diff --git a/src/equery/tests/test-depends-help.out b/src/equery/tests/test-depends-help.out deleted file mode 100644 index 356cd53..0000000 --- a/src/equery/tests/test-depends-help.out +++ /dev/null @@ -1,8 +0,0 @@ -List all direct dependencies matching a query pattern -Syntax: - depends <local-opts> pkgspec -<local-opts> is either of: - -d, --direct - search direct dependencies only (default) - -D, --indirect - search indirect dependencies (VERY slow) - -i, --only-installed - search installed in installed packages only - diff --git a/src/equery/tests/test-depends.sh b/src/equery/tests/test-depends.sh deleted file mode 100755 index e46d614..0000000 --- a/src/equery/tests/test-depends.sh +++ /dev/null @@ -1,27 +0,0 @@ -#! /bin/bash -# -# Copyright (c) 2004, Karl Trygve Kalleberg <karltk@gentoo.org> -# Copyright (c) 2004, Gentoo Foundation -# -# Licensed under the GNU General Public License, v2 - -. common-functions.sh - -tmpfile=$(tempfilename) - -test_depends() { -# equery skel gcc > ${tmpfile} - -# x=$(grep "app-shells/bash" ${tmpfile} | wc -l) - true -# assert_eq ${FUNCNAME} ${x} 1 - -# x=$(grep "virtual/libc" ${tmpfile} | wc -l) -# assert_eq ${FUNCNAME} ${x} 1 -} - -# Run tests - -#test_skel - -rm -f ${tmpfile}
\ No newline at end of file diff --git a/src/equery/tests/test-depgraph-help.out b/src/equery/tests/test-depgraph-help.out deleted file mode 100644 index 5b9fd22..0000000 --- a/src/equery/tests/test-depgraph-help.out +++ /dev/null @@ -1,7 +0,0 @@ -Display a dependency tree for a given package - -Syntax: - depgraph <local-opts> pkgspec -<local-opts> is either of: - -U, --no-useflags - do not show USE flags - -l, --linear - do not use fancy formatting diff --git a/src/equery/tests/test-depgraph.sh b/src/equery/tests/test-depgraph.sh deleted file mode 100755 index 016bb37..0000000 --- a/src/equery/tests/test-depgraph.sh +++ /dev/null @@ -1,27 +0,0 @@ -#! /bin/bash -# -# Copyright (c) 2004, Karl Trygve Kalleberg <karltk@gentoo.org> -# Copyright (c) 2004, Gentoo Foundation -# -# Licensed under the GNU General Public License, v2 - -. common-functions.sh - -tmpfile=$(tempfilename) - -test_depgraph() { - equery depgraph gcc > ${tmpfile} - - x=$(grep "app-shells/bash" ${tmpfile} | wc -l) - - assert_eq ${FUNCNAME} ${x} 1 - - x=$(grep "virtual/libc" ${tmpfile} | wc -l) - assert_eq ${FUNCNAME} ${x} 1 -} - -# Run tests - -test_depgraph - -rm -f ${tmpfile}
\ No newline at end of file diff --git a/src/equery/tests/test-files-help.out b/src/equery/tests/test-files-help.out deleted file mode 100644 index 846151f..0000000 --- a/src/equery/tests/test-files-help.out +++ /dev/null @@ -1,11 +0,0 @@ -List files owned by a particular package - -Syntax: - files <local-opts> <cat/>packagename<-version> - -Note: category and version parts are optional. - -<local-opts> is either of: - --timestamp - append timestamp - --md5sum - append md5sum - --type - prepend file type diff --git a/src/equery/tests/test-files.sh b/src/equery/tests/test-files.sh deleted file mode 100755 index ad0a5ea..0000000 --- a/src/equery/tests/test-files.sh +++ /dev/null @@ -1,61 +0,0 @@ -#! /bin/bash -# -# Copyright (c) 2004, Karl Trygve Kalleberg <karltk@gentoo.org> -# Copyright (c) 2004, Gentoo Foundation -# -# Licensed under the GNU General Public License, v2 - -. common-functions.sh - -tmpfile=$(tempfilename) - -strip_versioned_files() { - grep -v "/usr/share/doc" -} - -test_files() { - equery files bash > ${tmpfile} - - x=$(grep man ${tmpfile} | wc -l) - assert_ge ${FUNCNAME} $x 5 - - x=$(cat ${tmpfile} | wc -l) - assert_ge ${FUNCNAME} $x 25 -} - -test_files_timestamp() { - equery files --timestamp bash > ${tmpfile} - - x=$(grep "/bin/bash .*....-..-.. ..:..:.." ${tmpfile} | wc -l) - assert_eq ${FUNCNAME} $x 1 -} - -test_files_md5sum() { - equery files --md5sum bash > ${tmpfile} - - x=$(egrep "/bin/bash .*[0-9a-z]{30}" ${tmpfile} | wc -l) - assert_eq ${FUNCNAME} $x 1 -} - -test_files_type() { - - equery files --type bash > ${tmpfile} - - x=$(grep "file.*/bin/bash$" ${tmpfile} | wc -l) - assert_eq ${FUNCNAME} $x 1 - - x=$(grep "symlink.*/bin/rbash" ${tmpfile} | wc -l) - assert_eq ${FUNCNAME} $x 1 - - x=$(grep "dir.*/usr/share/man" ${tmpfile} | wc -l) - assert_ge ${FUNCNAME} $x 1 -} - -# Run tests - -test_files -test_files_timestamp -test_files_md5sum -test_files_type - -rm ${tmpfile}
\ No newline at end of file diff --git a/src/equery/tests/test-glsa-help.out b/src/equery/tests/test-glsa-help.out deleted file mode 100644 index e69de29..0000000 --- a/src/equery/tests/test-glsa-help.out +++ /dev/null diff --git a/src/equery/tests/test-hasuses-help.out b/src/equery/tests/test-hasuses-help.out deleted file mode 100644 index 1a05645..0000000 --- a/src/equery/tests/test-hasuses-help.out +++ /dev/null @@ -1,9 +0,0 @@ -List all packages with a particular USE flag -Syntax: - list <local-opts> useflag -<local-opts> is either of: - -i, --installed - search installed packages (default) - -I, --exclude-installed - do not search installed packages - -p, --portage-tree - also search in portage tree (/usr/portage) - -o, --overlay-tree - also search in overlay tree (/usr/local/portage /usr/local/overlays/gentoo-boblycat) - diff --git a/src/equery/tests/test-help.out b/src/equery/tests/test-help.out deleted file mode 100644 index 26517f4..0000000 --- a/src/equery/tests/test-help.out +++ /dev/null @@ -1,21 +0,0 @@ -Usage: equery <global-opts> command <local-opts> -where <global-opts> is one of - -q, --quiet - minimal output - -C, --nocolor - turn off colours - -h, --help - this help screen - -V, --version - display version info -where command(short) is one of - belongs(b) <local-opts> files... - list all packages owning files... - changes(c) - not implemented yet - check(k) pkgspec - check MD5sums and timestamps of pkgspec's files - depends(d) <local-opts> pkgspec - list all direct dependencies matching pkgspec - depgraph(g) <local-opts> pkgspec - display a dependency tree for pkgspec - files(f) <local-opts> pkgspec - list files owned by pkgspec - glsa(a) - not implemented yet - hasuses(h) <local-opts> pkgspec - list all packages with useflag - list(l) <local-opts> pkgspec - list all packages matching pkgspec - size(s) <local-opts> pkgspec - print size of files contained in package pkgspec - stats(t) - not implemented yet - uses(u) <local-opts> pkgspec - display USE flags for pkgspec - which(w) pkgspec - print full path to ebuild for package pkgspec - diff --git a/src/equery/tests/test-help.sh b/src/equery/tests/test-help.sh deleted file mode 100755 index 618aac1..0000000 --- a/src/equery/tests/test-help.sh +++ /dev/null @@ -1,105 +0,0 @@ -#! /bin/sh -# -# Copyright (c) 2004, Karl Trygve Kalleberg <karltk@gentoo.org> -# Copyright (c) 2004, Gentoo Foundation -# -# Licensed under the GNU General Public License, v2 - -. common-functions.sh - -tmpfile=$(tempfilename) - -test_equery_help() { - equery --help > ${tmpfile} - assert_samefile ${FUNCNAME} ${tmpfile} test-help.out - -} - -test_belongs_help() { - equery belongs --help > ${tmpfile} - assert_samefile ${FUNCNAME} ${tmpfile} test-belongs-help.out -} - -test_changes_help() { - equery changes --help > ${tmpfile} - assert_samefile ${FUNCNAME} ${tmpfile} test-changes-help.out -} - -test_check_help() { - equery check --help > ${tmpfile} - assert_samefile ${FUNCNAME} ${tmpfile} test-check-help.out -} - -test_depends_help() { - equery depends --help > ${tmpfile} - assert_samefile ${FUNCNAME} ${tmpfile} test-depends-help.out -} - -test_depgraph_help() { - equery depgraph --help > ${tmpfile} - assert_samefile ${FUNCNAME} ${tmpfile} test-depgraph-help.out -} - -test_files_help() { - equery files --help > ${tmpfile} - assert_samefile ${FUNCNAME} ${tmpfile} test-files-help.out -} - -test_glsa_help() { - equery glsa --help > ${tmpfile} - assert_samefile ${FUNCNAME} ${tmpfile} test-glsa-help.out -} - -test_hasuses_help() { - equery hasuses --help > ${tmpfile} - assert_samefile ${FUNCNAME} ${tmpfile} test-hasuses-help.out -} - -test_list_help() { - equery list --help > ${tmpfile} - assert_samefile ${FUNCNAME} ${tmpfile} test-list-help.out -} - -test_size_help() { - equery size --help > ${tmpfile} - assert_samefile ${FUNCNAME} ${tmpfile} test-size-help.out -} - -test_stats_help() { - equery stats --help > ${tmpfile} - assert_samefile ${FUNCNAME} ${tmpfile} test-stats-help.out -} - -test_uses_help() { - equery uses --help > ${tmpfile} - assert_samefile ${FUNCNAME} ${tmpfile} test-uses-help.out -} - -test_which_help() { - equery which --help > ${tmpfile} - assert_samefile ${FUNCNAME} ${tmpfile} test-which-help.out -} - - -# run tests - -if [ "`hostname`" != "sky" ] ; then - echo "Testing framework is beta and machine dependent; some tests will fail!" -fi - -test_equery_help -test_belongs_help -test_check_help -test_changes_help -test_depends_help -test_depgraph_help -test_files_help -test_glsa_help -test_hasuses_help -test_list_help -test_size_help -test_stats_help -test_uses_help -test_which_help - -rm -f *.tmp
\ No newline at end of file diff --git a/src/equery/tests/test-list-help.out b/src/equery/tests/test-list-help.out deleted file mode 100644 index 82d1fb0..0000000 --- a/src/equery/tests/test-list-help.out +++ /dev/null @@ -1,9 +0,0 @@ -List all packages matching a query pattern -Syntax: - list <local-opts> pkgspec -<local-opts> is either of: - -i, --installed - search installed packages (default) - -I, --exclude-installed - do not search installed packages - -p, --portage-tree - also search in portage tree (/usr/portage) - -o, --overlay-tree - also search in overlay tree (/usr/local/portage /usr/local/overlays/gentoo-boblycat) - diff --git a/src/equery/tests/test-list.sh b/src/equery/tests/test-list.sh deleted file mode 100755 index a43048b..0000000 --- a/src/equery/tests/test-list.sh +++ /dev/null @@ -1,40 +0,0 @@ -#! /bin/bash -# -# Copyright (c) 2004, Karl Trygve Kalleberg <karltk@gentoo.org> -# Copyright (c) 2004, Gentoo Foundation -# -# Licensed under the GNU General Public License, v2 - -. common-functions.sh - -tmpfile=$(tempfilename) - -test_list() { - equery list > ${tmpfile} - -# should test tty output as well -# pkgs=$(cat ${tmpfile} | wc -l) -# x=$(grep "[I--]" ${tmpfile} | wc -l) -# assert_eq ${FUNCNAME} ${pkgs} ${x} - - x=$(grep "app-shells/bash" ${tmpfile} | wc -l) - assert_ge ${FUNCNAME} $x 1 -} - -test_list_installed() { - test_list -} - -test_list_portage_tree() { - equery list -I -p > ${tmpfile} -} - -test_list_overlay_tree() { - equery list -I -o > ${tmpfile} -} - -# Run tests - -test_list - -rm -f ${tmpfile}
\ No newline at end of file diff --git a/src/equery/tests/test-size-help.out b/src/equery/tests/test-size-help.out deleted file mode 100644 index c0c63a4..0000000 --- a/src/equery/tests/test-size-help.out +++ /dev/null @@ -1,6 +0,0 @@ -Print size total size of files contained in a given package -Syntax: - size <local-opts> pkgspec -<local-opts> is either of: - -b, --bytes - report size in bytes - diff --git a/src/equery/tests/test-size.sh b/src/equery/tests/test-size.sh deleted file mode 100755 index 126a5db..0000000 --- a/src/equery/tests/test-size.sh +++ /dev/null @@ -1,27 +0,0 @@ -#! /bin/bash -# -# Copyright (c) 2004, Karl Trygve Kalleberg <karltk@gentoo.org> -# Copyright (c) 2004, Gentoo Foundation -# -# Licensed under the GNU General Public License, v2 - -. common-functions.sh - -tmpfile=$(tempfilename) - -test_size() { - equery size gcc > ${tmpfile} - - x=$(grep "sys-devel/gcc" ${tmpfile} | wc -l) - - assert_ge ${FUNCNAME} ${x} 1 - - x=$(egrep "size\([0-9]+\)" ${tmpfile} | wc -l) - assert_ge ${FUNCNAME} ${x} 1 -} - -# Run tests - -test_size - -rm -f ${tmpfile}
\ No newline at end of file diff --git a/src/equery/tests/test-stats-help.out b/src/equery/tests/test-stats-help.out deleted file mode 100644 index e69de29..0000000 --- a/src/equery/tests/test-stats-help.out +++ /dev/null diff --git a/src/equery/tests/test-uses-help.out b/src/equery/tests/test-uses-help.out deleted file mode 100644 index d350e00..0000000 --- a/src/equery/tests/test-uses-help.out +++ /dev/null @@ -1,7 +0,0 @@ -Display USE flags for a given package - -Syntax: - uses <local-opts> pkgspec -<local-opts> is either of: - -a, --all - include non-installed packages - diff --git a/src/equery/tests/test-uses.sh b/src/equery/tests/test-uses.sh deleted file mode 100755 index d694483..0000000 --- a/src/equery/tests/test-uses.sh +++ /dev/null @@ -1,39 +0,0 @@ -#! /bin/bash -# -# Copyright (c) 2004, Karl Trygve Kalleberg <karltk@gentoo.org> -# Copyright (c) 2004, Gentoo Foundation -# -# Licensed under the GNU General Public License, v2 - -. common-functions.sh - -tmpfile=$(tempfilename) - -test_uses() { - equery uses gcc > ${tmpfile} - - x=$(grep "static" ${tmpfile} | wc -l) - - assert_eq ${FUNCNAME} ${x} 1 - - x=$(cat ${tmpfile} | wc -l) - assert_ge ${FUNCNAME} $x 7 -} - -test_uses_all() { - equery uses -a uclibc > ${tmpfile} - - x=$(grep "static" ${tmpfile} | wc -l) - assert_ge ${FUNCNAME} ${x} 1 - - x=$(cat ${tmpfile} | wc -l) - assert_ge ${FUNCNAME} $x 5 - -} - -# Run tests - -test_uses -test_uses_all - -rm -f ${tmpfile}
\ No newline at end of file diff --git a/src/equery/tests/test-which-help.out b/src/equery/tests/test-which-help.out deleted file mode 100644 index 8bf337e..0000000 --- a/src/equery/tests/test-which-help.out +++ /dev/null @@ -1,3 +0,0 @@ -Print full path to ebuild for a given package -Syntax: - size pkgspec diff --git a/src/equery/tests/test-which.sh b/src/equery/tests/test-which.sh deleted file mode 100755 index 491868f..0000000 --- a/src/equery/tests/test-which.sh +++ /dev/null @@ -1,22 +0,0 @@ -#! /bin/bash -# -# Copyright (c) 2004, Karl Trygve Kalleberg <karltk@gentoo.org> -# Copyright (c) 2004, Gentoo Foundation -# -# Licensed under the GNU General Public License, v2 - -. common-functions.sh - -tmpfile=$(tempfilename) - -test_which() { - file=$(equery which gcc) - - assert_exists ${FUNCNAME} ${file} -} - -# Run tests - -test_which - -rm -f ${tmpfile}
\ No newline at end of file diff --git a/src/eread/AUTHORS b/src/eread/AUTHORS deleted file mode 100644 index 68064ce..0000000 --- a/src/eread/AUTHORS +++ /dev/null @@ -1,2 +0,0 @@ -Author: Donnie Berkholz <dberkholz@gentoo.org> -Updated by: Uwe Klosa <uwe.klosa@gmail.com> diff --git a/src/eread/Makefile b/src/eread/Makefile deleted file mode 100644 index 1d9b284..0000000 --- a/src/eread/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright 2006 Gentoo Technologies, Inc. -# Distributed under the terms of the GNU General Public License v2 -# -# $Header$ - -include ../../makedefs.mak - -all: - echo "ELY (n.) The first, tiniest inkling you get that something, somewhere, has gone terribly wrong." - -dist: - mkdir -p ../../$(distdir)/src/eread - cp AUTHORS Makefile eread eread.1 ../../$(distdir)/src/eread/ - -install: - - install -m 0755 eread $(bindir)/ - install -d $(docdir)/eread - install -m 0644 AUTHORS $(docdir)/eread/ - install -m 0644 eread.1 $(mandir)/ diff --git a/src/eread/eread b/src/eread/eread deleted file mode 100755 index c6d4de1..0000000 --- a/src/eread/eread +++ /dev/null @@ -1,94 +0,0 @@ -#!/bin/bash - -# This is a script to read portage log items from einfo, ewarn etc, new in the -# portage-2.1 series. -# -# Author: Donnie Berkholz <spyderous@gentoo.org> -# Updated by: Uwe Klosa <uwe.klosa@gmail.com> - -# set decent PATH for bug 172969 - -PATH=/usr/bin:/bin:${PATH} - -# Set ELOGDIR -PORT_LOGDIR="$(portageq envvar PORT_LOGDIR)" -[ "$PORT_LOGDIR" = "" ] && PORT_LOGDIR="/var/log/portage" -ELOGDIR="$PORT_LOGDIR/elog" - -# Verify that ELOGDIR exists -if [ ! -d "$ELOGDIR" ]; then - echo "ELOG directory: $ELOGDIR does not exist!" - exit 1 -fi - -# Use the pager from the users environment -[ -z "$PAGER" ] && PAGER="less" - -# Set up select prompt -PS3="Choice? " - -select_loop() { - ANY_FILES=$(find . -type f) - ANY_FILES=$(echo ${ANY_FILES} | sed -e "s:\./::g") - - if [[ -z ${ANY_FILES} ]]; then - echo "No log items to read" - break - fi - - echo - echo "This is a list of portage log items. Choose a number to view that file or type q to quit." - echo - - # Pick which file to read - select FILE in ${ANY_FILES}; do - case ${REPLY} in - q) - echo "Quitting" - QUIT="yes" - break - ;; - *) - if [ -f "$FILE" ]; then - ${PAGER} ${FILE} - read -p "Delete file? [y/N] " DELETE - case ${DELETE} in - q) - echo "Quitting" - QUIT="yes" - break - ;; - y|Y) - rm -f ${FILE} - SUCCESS=$? - if [[ ${SUCCESS} = 0 ]]; then - echo "Deleted ${FILE}" - else - echo "Unable to delete ${FILE}" - fi - ;; - # Empty string defaults to N (save file) - n|N|"") - echo "Saving ${FILE}" - ;; - *) - echo "Invalid response. Saving ${FILE}" - ;; - esac - else - echo - echo "Invalid response." - fi - ;; - esac - break - done -} - -pushd ${ELOGDIR} > /dev/null - -until [[ -n ${QUIT} ]]; do - select_loop -done - -popd > /dev/null diff --git a/src/eread/eread.1 b/src/eread/eread.1 deleted file mode 100644 index 5e18214..0000000 --- a/src/eread/eread.1 +++ /dev/null @@ -1,12 +0,0 @@ -.TH "eread" "1" "1.0" "Donnie Berkholz" "gentoolkit" -.SH "NAME" -.LP -eread \- Gentoo: Tool to display and manage ELOG files from portage -.SH "SYNTAX" -.LP -eread -.SH "DESCRIPTION" -.LP -This tool is used to display and manage ELOG files produced by portage version 2.1 and higher. -.SH "ENVIRONMENT VARIABLES" -The eread utility uses the PAGER environment variable to display the ELOG files. If the variable is not set, it defaults to /usr/bin/less. diff --git a/src/euse/AUTHORS b/src/euse/AUTHORS deleted file mode 100644 index 12e6db7..0000000 --- a/src/euse/AUTHORS +++ /dev/null @@ -1,2 +0,0 @@ -* original perl version: Arun Bhanu <codebear@gentoo.org> -* new bash version: Marius Mauch <genone@gentoo.org> diff --git a/src/euse/ChangeLog b/src/euse/ChangeLog deleted file mode 100644 index cb50dbb..0000000 --- a/src/euse/ChangeLog +++ /dev/null @@ -1,9 +0,0 @@ - -2004-01-07 Karl Trygve Kalleberg <karltk@gentoo.org> - * Added Makefile - * Updated from app-portage/gentoolkit - * Reformatted ChangeLog - -2003-05-09 Arun Bhanu <codebear@gentoo.org> - * Initial commit to gentoolkit. - diff --git a/src/euse/Makefile b/src/euse/Makefile deleted file mode 100644 index d1ad804..0000000 --- a/src/euse/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright 2004 Karl Trygve Kalleberg <karltk@gentoo.org> -# Copyright 2004 Gentoo Technologies, Inc. -# Distributed under the terms of the GNU General Public License v2 -# -# $Header$ - -include ../../makedefs.mak - -all: - echo "PIMPERNE (n.) One of those rubber nodules found on the underneath side of a lavatory seat." - -dist: - mkdir -p ../../$(distdir)/src/euse/ - cp Makefile AUTHORS ChangeLog euse euse.1 ../../$(distdir)/src/euse/ - -install: - install -m 0755 euse $(bindir)/ - install -d $(docdir)/euse - install -m 0644 AUTHORS ChangeLog $(docdir)/euse/ - install -m 0644 euse.1 $(mandir)/ diff --git a/src/euse/euse b/src/euse/euse deleted file mode 100755 index f9fd2fd..0000000 --- a/src/euse/euse +++ /dev/null @@ -1,551 +0,0 @@ -#!/bin/bash - -# $Header$ - -# bash replacement for the original euse by Arun Bhanu -# Author: Marius Mauch <genone@gentoo.org> -# Version: 0.2 -# Licensed under the GPL v2 - -PROGRAM_NAME=euse -PROGRAM_VERSION=0.1 - -MAKE_CONF_PATH=/etc/make.conf -MAKE_GLOBALS_PATH=/etc/make.globals -MAKE_PROFILE_PATH=/etc/make.profile -MAKE_CONF_BACKUP_PATH=/etc/make.conf.euse_backup - -[ -z "${MODE}" ] && MODE="showhelp" # available operation modes: showhelp, showversion, showdesc, showflags, modify - -parse_arguments() { - if [ -z "${1}" ]; then - return - fi - while [ -n "${1}" ]; do - case "${1}" in - -h | --help) MODE="showhelp";; - -v | --version) MODE="showversion";; - -i | --info) MODE="showdesc";; - -I | --info-installed) MODE="showinstdesc";; - -l | --local) SCOPE="local";; - -g | --global) SCOPE="global";; - -a | --active) MODE="showflags";; - -E | --enable) MODE="modify"; ACTION="add";; - -D | --disable) MODE="modify"; ACTION="remove";; - -P | --prune) MODE="modify"; ACTION="prune";; - -*) - echo "ERROR: unknown option ${1} specified." - echo - MODE="showhelp" - ;; - "%active") - get_useflags - ARGUMENTS="${ARGUMENTS} ${ACTIVE_FLAGS[9]}" - ;; - *) - ARGUMENTS="${ARGUMENTS} ${1}" - ;; - esac - shift - done -} - -error() { - echo "ERROR: ${1}" - set +f - exit 1 -} - -get_real_path() { - set -P - cd "$1" - pwd - cd "$OLDPWD" - set +P -} - -check_sanity() { - # file permission tests - local descdir - local make_defaults - - descdir="$(get_portdir)/profiles" - - [ ! -r "${MAKE_CONF_PATH}" ] && error "${MAKE_CONF_PATH} is not readable" - [ ! -r "${MAKE_GLOBALS_PATH}" ] && error "${MAKE_GLOBALS_PATH} is not readable" - [ ! -h "${MAKE_PROFILE_PATH}" ] && error "${MAKE_PROFILE_PATH} is not a symlink" - [ -z "$(get_portdir)" ] && error "\$PORTDIR couldn't be determined" - [ ! -d "${descdir}" ] && error "${descdir} does not exist or is not a directory" - [ ! -r "${descdir}/use.desc" ] && error "${descdir}/use.desc is not readable" - [ ! -r "${descdir}/use.local.desc" ] && error "${descdir}/use.local.desc is not readable" - for make_defaults in $(get_all_make_defaults); do - [ ! -r "$make_defaults" ] && error "$_make_defaults is not readable" - done -# [ ! -r "$(get_make_defaults)" ] && error "$(get_make_defaults) is not readable" - [ "${MODE}" == "modify" -a ! -w "${MAKE_CONF_PATH}" ] && error ""${MAKE_CONF_PATH}" is not writable" -} - -showhelp() { -cat << HELP -${PROGRAM_NAME} v${PROGRAM_VERSION} - -Syntax: ${PROGRAM_NAME} <option> [suboptions] [useflaglist] - -Options: -h, --help - show this message - -v, --version - show version information - -i, --info - show descriptions for the given useflags - -I, --info-installed - show descriptions for the given useflags and - their current impact on the installed system - -g, --global - show only global use flags (suboption) - -l, --local - show only local use flags (suboption) - -a, --active - show currently active useflags and their origin - -E, --enable - enable the given useflags - -D, --disable - disable the given useflags - -P, --prune - remove all references to the given flags from - make.conf to revert to default settings - -Notes: ${PROGRAM_NAME} currently only works for global flags defined - in make.globals, make.defaults or make.conf, it doesn't handle - use.defaults, use.mask or package.use yet (see portage(5) for details on - these files). It also might have issues with cascaded profiles. - If multiple options are specified only the last one will be used. -HELP -} - -showversion() { -cat << VER -${PROGRAM_NAME} v${PROGRAM_VERSION} -Written by Marius Mauch - -Copyright (C) 2004-2008 Gentoo Foundation, Inc. -This is free software; see the source for copying conditions. -VER -} - -# remove duplicate flags from the given list in both positive and negative forms -# (but unlike portage always keep the last value even if it's negative) -# Otherwise the status flags could be incorrect if a flag appers multiple times in -# one location (like make.conf). -# Using python here as bash sucks for list handling. -# NOTE: bash isn't actually that bad at handling lists -- sh is. This may be -# worth another look to avoid calling python unnecessariy. Or we could -# just write the whole thing in python. ;) -reduce_incrementals() { - echo $@ | python -c "import sys -r=[] -for x in sys.stdin.read().split(): - if x[0] == '-' and x[1:] in r: - r.remove(x[1:]) - r.append(x) - elif x[0] != '-' and '-'+x in r: - r.remove('-'+x) - r.append(x) - elif x == '-*': - r = [] - r.append(x) - elif x not in r: - r.append(x) -print ' '.join(r)" -} - -# the following function creates a bash array ACTIVE_FLAGS that contains the -# global use flags, indexed by origin: 0: environment, 1: make.conf, -# 2: make.defaults, 3: make.globals -get_useflags() { - # only calculate once as calling emerge is painfully slow - [ -n "${USE_FLAGS_CALCULATED}" ] && return - - # backup portdir so get_portdir() doesn't give false results later - portdir_backup="${PORTDIR}" - - ACTIVE_FLAGS[0]="$(reduce_incrementals ${USE})" - USE="" - source "${MAKE_CONF_PATH}" - ACTIVE_FLAGS[1]="$(reduce_incrementals ${USE})" - USE="" - for x in $(get_all_make_defaults); do - source "${x}" - ACTIVE_FLAGS[2]="$(reduce_incrementals ${ACTIVE_FLAGS[2]} ${USE})" - done - USE="" - source "${MAKE_GLOBALS_PATH}" - ACTIVE_FLAGS[3]="$(reduce_incrementals ${USE})" - - # restore saved env variables - USE="${ACTIVE_FLAGS[0]}" - PORTDIR="${portdir_backup}" - - # get the currently active USE flags as seen by portage, this has to be after - # restoring USE or portage won't see the original environment - ACTIVE_FLAGS[9]="$(emerge --info | grep 'USE=' | cut -b 5- | sed -e 's:"::g')" #' - USE_FLAGS_CALCULATED=1 -} - -# get the list of all known USE flags by reading use.desc and/or use.local.desc -# (depending on the value of $SCOPE) -get_useflaglist() { - local descdir - - descdir="$(get_portdir)/profiles" - - if [ -z "${SCOPE}" -o "${SCOPE}" == "global" ]; then - egrep "^[^# ]+ +-" "${descdir}/use.desc" | cut -d\ -f 1 - fi - if [ -z "${SCOPE}" -o "${SCOPE}" == "local" ]; then - egrep "^[^# :]+:[^ ]+ +-" "${descdir}/use.local.desc" | cut -d: -f 2 | cut -d\ -f 1 - fi -} - -# get all make.defaults by traversing the cascaded profile directories -get_all_make_defaults() { - local curdir - local parent - local rvalue - - curdir="${1:-$(get_real_path ${MAKE_PROFILE_PATH})}" - - [ -f "${curdir}/make.defaults" ] && rvalue="${curdir}/make.defaults ${rvalue}" - if [ -f "${curdir}/parent" ]; then - for parent in $(egrep -v '(^#|^ *$)' ${curdir}/parent); do - pdir="$(get_real_path ${curdir}/${parent})" - rvalue="$(get_all_make_defaults ${pdir}) ${rvalue}" - done - fi - - echo "${rvalue}" -} - -# get the path to make.defaults by traversing the cascaded profile directories -get_make_defaults() { - local curdir - local parent - - curdir="${1:-$(get_real_path ${MAKE_PROFILE_PATH})}" - - if [ ! -f "${curdir}/make.defaults" -a -f "${curdir}/parent" ]; then - for parent in $(egrep -v '(^#|^ *$)' ${curdir}/parent); do - if [ -f "$(get_make_defaults ${curdir}/${parent})" ]; then - curdir="${curdir}/${parent}" - break - fi - done - fi - - echo "${curdir}/make.defaults" -} - -# little helper function to get the status of a given flag in one of the -# ACTIVE_FLAGS elements. Arguments are 1: flag to test, 2: index of ACTIVE_FLAGS, -# 3: echo value for positive (and as lowercase for negative) test result, -# 4 (optional): echo value for "missing" test result, defaults to blank -get_flagstatus_helper() { - if echo " ${ACTIVE_FLAGS[${2}]} " | grep " ${1} " > /dev/null; then - echo -n "${3}" - elif echo " ${ACTIVE_FLAGS[${2}]} " | grep " -${1} " > /dev/null; then - echo -n "$(echo ${3} | tr [[:upper:]] [[:lower:]])" - else - echo -n "${4:- }" - fi -} - -# prints a status string for the given flag, each column indicating the presence -# for portage, in the environment, in make.conf, in make.defaults and in make.globals. -# full positive value would be "[+ECDG]", full negative value would be [-ecdg], -# full missing value would be "[- ]" (portage only sees present or not present) -get_flagstatus() { - get_useflags - - echo -n '[' - get_flagstatus_helper "${1}" 9 "+" "-" - get_flagstatus_helper "${1}" 0 "E" - get_flagstatus_helper "${1}" 1 "C" - get_flagstatus_helper "${1}" 2 "D" - get_flagstatus_helper "${1}" 3 "G" - echo -n '] ' -} - -# faster replacement to `portageq portdir` -get_portdir() { - if [ -z "${PORTDIR}" ]; then - use_backup="${USE}" - source "${MAKE_GLOBALS_PATH}" - for x in $(get_all_make_defaults); do - source "${x}" - done - source "${MAKE_CONF_PATH}" - USE="${use_backup}" - fi - echo "${PORTDIR}" -} - -# This function takes a list of use flags and shows the status and -# the description for each one, honoring $SCOPE -showdesc() { - local descdir - local current_desc - local found_one - local args - - args="${*:-*}" - - if [ -z "${SCOPE}" ]; then - SCOPE="global" showdesc ${args} - echo - SCOPE="local" showdesc ${args} - return - fi - - descdir="$(get_portdir)/profiles" - - [ "${SCOPE}" == "global" ] && echo "global use flags (searching: ${args})" - [ "${SCOPE}" == "local" ] && echo "local use flags (searching: ${args})" - echo "************************************************************" - - if [ "${args}" == "*" ]; then - args="$(get_useflaglist | sort -u)" - fi - - set ${args} - - foundone=0 - while [ -n "${1}" ]; do - if [ "${SCOPE}" == "global" ]; then - if grep "^${1} *-" "${descdir}/use.desc" > /dev/null; then - get_flagstatus "${1}" - foundone=1 - fi - grep "^${1} *-" "${descdir}/use.desc" - fi - # local flags are a bit more complicated as there can be multiple - # entries per flag and we can't pipe into printf - if [ "${SCOPE}" == "local" ]; then - if grep ":${1} *-" "${descdir}/use.local.desc" > /dev/null; then - foundone=1 - fi - grep ":${1} *-" "${descdir}/use.local.desc" \ - | sed -e "s/^\([^:]\+\):\(${1}\) *- *\(.\+\)/\1|\2|\3/g" \ - | while read line; do - pkg="$(echo $line | cut -d\| -f 1)" - flag="$(echo $line | cut -d\| -f 2)" - desc="$(echo $line | cut -d\| -f 3)" - get_flagstatus "${flag}" - printf "%s (%s):\n%s\n\n" "${flag}" "${pkg}" "${desc}" - done - fi - shift - done - - if [ ${foundone} == 0 ]; then - echo "no matching entries found" - fi -} - -# Works like showdesc() but displays only descriptions of which the appropriate -# ebuild is installed and prints the name of those packages. -showinstdesc() { - local descdir - local current_desc - local args - local -i foundone=0 - local OIFS="$IFS" - - args=("${@:-*}") - - case "${SCOPE}" in - "global") echo "global use flags (searching: ${args})";; - "local") echo "local use flags (searching: ${args})";; - *) SCOPE="global" showinstdesc "${args[@]}" - echo - SCOPE="local" showinstdesc "${args[@]}" - return;; - esac - - descdir="$(get_portdir)/profiles" - echo "************************************************************" - - if [ "${args}" = "*" ]; then - args="$(get_useflaglist | sort -u)" - fi - - set "${args[@]}" - - while [ -n "${1}" ]; do - case "${SCOPE}" in - "global") - if desc=$(grep "^${1} *-" "${descdir}/use.desc"); then - get_flagstatus "${1}" - echo "$desc" - # get list of installed packages matching this USE flag. - IFS=$'\n' - packages=($(equery -q -C hasuse -i "${1}" | awk '{ print $(NF-1) }' | sort)) - foundone+=${#packages[@]} - printf "\nInstalled packages matching this USE flag: " - if [ ${foundone} -gt 0 ]; then - echo $'\n'"${packages[*]}" - else - echo "none" - fi - fi - ;; - "local") - # local flags are a bit more complicated as there can be multiple - # entries per flag and we can't pipe into printf - IFS=': ' # Use a space instead of a dash because dashes occur in cat/pkg - while read pkg flag desc; do - # print name only if package is installed - # NOTE: If we implement bug #114086 's enhancement we can just use the - # exit status of equery instead of a subshell and pipe to wc -l - if [ $(equery -q -C list -i -e "${pkg}" | wc -l) -gt 0 ]; then - foundone=1 - IFS="$OIFS" - get_flagstatus "${flag}" - IFS=': ' - printf "%s (%s):\n%s\n\n" "${flag}" "${pkg}" "${desc#- }" - fi - done < <(grep ":${1} *-" "${descdir}/use.local.desc") - ;; - esac - shift - done - - if [ ${foundone} -lt 1 ]; then - echo "no matching entries found" - fi - IFS="$OIFS" -} - -# show a list of all currently active flags and where they are activated -showflags() { - local args - - get_useflags - - args="${*:-*}" - - if [ "${args}" == "*" ]; then - args="$(get_useflaglist | sort -u)" - fi - - set ${args} - - while [ -n "${1}" ]; do - if echo " ${ACTIVE_FLAGS[9]} " | grep " ${1} " > /dev/null; then - printf "%-20s" ${1} - get_flagstatus ${1} - echo - fi - shift - done -} - -# two small helpers to add or remove a flag from a USE string -add_flag() { - NEW_MAKE_CONF_USE="${NEW_MAKE_CONF_USE} ${1}" -} - -remove_flag() { - NEW_MAKE_CONF_USE="${NEW_MAKE_CONF_USE// ${1} / }" -} - -# USE flag modification function. Mainly a loop with calls to add_flag and -# remove_flag to create a new USE string which is then inserted into make.conf. -modify() { - if [ -z "${*}" ]; then - if [ "${ACTION}" != "prune" ]; then - echo "WARNING: no USE flags listed for modification, do you really" - echo " want to ${ACTION} *all* known USE flags?" - echo " If you don't please press Ctrl-C NOW!!!" - sleep 5 - set $(get_useflaglist | sort -u) - fi - fi - - get_useflags - - NEW_MAKE_CONF_USE=" ${ACTIVE_FLAGS[1]} " - - while [ -n "${1}" ]; do - if [ "${ACTION}" == "add" ]; then - if echo " ${NEW_MAKE_CONF_USE} " | grep " ${1} " > /dev/null; then - shift - elif echo " ${NEW_MAKE_CONF_USE} " | grep " -${1} " > /dev/null; then - remove_flag "-${1}" - else - add_flag "${1}" - shift - fi - elif [ "${ACTION}" == "remove" ]; then - if echo " ${NEW_MAKE_CONF_USE} " | grep " -${1} " > /dev/null; then - shift - elif echo " ${NEW_MAKE_CONF_USE} " | grep " ${1} " > /dev/null; then - remove_flag "${1}" - else - add_flag "-${1}" - shift - fi - elif [ "${ACTION}" == "prune" ]; then - if echo " ${NEW_MAKE_CONF_USE} " | grep " ${1} " > /dev/null; then - remove_flag "${1}" - elif echo " ${NEW_MAKE_CONF_USE} " | grep " -${1} " > /dev/null; then - remove_flag "-${1}" - fi - shift - fi - done - - #echo "old flags:" - #echo ${ACTIVE_FLAGS[1]} - #echo - #echo "new flags:" - #echo ${NEW_MAKE_CONF_USE} - - # a little loop to add linebreaks so we don't end with one ultra-long line - NEW_MAKE_CONF_USE_2="" - for x in ${NEW_MAKE_CONF_USE}; do - if [ $(((${#NEW_MAKE_CONF_USE_2}%70)+${#x}+2)) -gt 70 ]; then - NEW_MAKE_CONF_USE_2="${NEW_MAKE_CONF_USE_2}\\ \\n $x " - else - NEW_MAKE_CONF_USE_2="${NEW_MAKE_CONF_USE_2}${x} " - fi - done - - # make a backup just in case the user doesn't like the new make.conf - cp -p "${MAKE_CONF_PATH}" "${MAKE_CONF_BACKUP_PATH}" - - # as sed doesn't really work with multi-line patterns we have to replace USE - # on our own here. Basically just skip everything between USE=" and the - # closing ", printing our new USE line there instead. - inuse=0 - had_use=0 - x=0 - (while [ "$x" -eq "0" ]; do - read -r line - x="$?" - [ "${line:0:4}" == "USE=" ] && inuse=1 - [ "${inuse}" == "0" ] && echo -E "${line}" - if [ "${inuse}" == "1" ] && echo "${line}" | egrep '" *(#.*)?$' > /dev/null; then - echo -n 'USE="' - echo -ne "${NEW_MAKE_CONF_USE_2%% }" - echo '"' - inuse=0 - had_use=1 - fi - done - if [ ${had_use} -eq 0 ]; then - echo -n 'USE="' - echo -ne "${NEW_MAKE_CONF_USE_2%% }" - echo '"' - fi ) < "${MAKE_CONF_BACKUP_PATH}" | sed -e 's:\\ $:\\:' > "${MAKE_CONF_PATH}" - - echo "${MAKE_CONF_PATH} was modified, a backup copy has been placed at ${MAKE_CONF_BACKUP_PATH}" -} - -##### main program comes now ##### - -# disable globbing as it fucks up with args=* -set -f -parse_arguments "$@" -check_sanity - -eval ${MODE} ${ARGUMENTS} -set +f diff --git a/src/euse/euse.1 b/src/euse/euse.1 deleted file mode 100644 index b5148fd..0000000 --- a/src/euse/euse.1 +++ /dev/null @@ -1,102 +0,0 @@ -.TH "EUSE" "1" "2004-10-17" "Gentoo Linux" "Gentoo Toolkit" -.SH "NAME" -euse \- Gentoo: command line USE flag editor -.SH "SYNOPSIS" -.B euse -\fI<option> [suboption] [useflaglist]\fB -.SH "DESCRIPTION" -.PP -.I euse -is used to set(disable/enable) USE flags in /etc/make.conf without having to edit -the file directly. It is also used to get detail information about use flags -like description, status of flags(enabled/disabled), type of flag(global/local) -etc. -.SH "OPTIONS " -.TP -\fB\-E, \-\-enable\fI -Enables USE flag(s) in make.conf. It accepts one or more space seperated -USE flags as parameters. -.TP -\fB\-D, \-\-disable\fI -Disables USE flag(s) in make.conf. Puts a '\-' sign in front of the USE flag -and appends it to the USE setting in make.conf. It accepts one or more -space seperated USE flags as parameters. -.TP -\fB\-P, \-\-prune\fI -Removes USE flag(s) in make.conf. Removes all positive and negative references to -the given USE flags from make.conf. -.TP -\fB\-i, \-\-info\fI -Prints detail information about the USE flag(s). If no arguments are given then -it assumes you want information for all USE flags. If one or more -arguments are given (space separated) then only information for those flags is -printed. -.TP -\fB\-I, \-\-info\-installed\fI -Same as \-\-info, except that it will also list the currently installed packages that are utilizing the flag. -.sp -.RS -The output is in the following format: -.br -\fB[\- cD ]\fI alpha \- indicates that architecture ... -.br -\fB[\- ]\fI moznocompose (net\-www/mozilla): -.br -Disable building of mozilla's web page composer -.br -The indicators in the first column are: -.IP is_active -+ if the flag is seen as active by portage, \- if not -.IP is_in_env -E if the flag is enabled in the environment, e if it is -disabled in the environment, nothing if it's not affected -by the environment -.IP is_in_make_conf -C if the flag is enabled in make.conf, c if it is -disabled in make.conf, nothing if it's not affected -by make.conf -.IP is_in_make_defaults -D if the flag is enabled in make.defaults, d if it is -disabled in make.defaults, nothing if it's not affected -by make.defaults -.IP is_in_make_globals -G if the flag is enabled in make.globals, g if it is -disabled in make.globals, nothing if it's not affected -by make.globals -.br -Then follows the name of the flag, for local flags the -package name and then the description (on a new line for -local flags). -.TP -\fB\-a, \-\-active\fI -Shows all currently active USE flags and where they are activated (see -description for \fB\-\-info\fI). -.TP -\fB\-h, \-\-help\fI -Show the help message listing all the available flags and a short description -.TP -\fB\-v, \-\-version\fI -Show the version information -.SH "FILES" -/etc/make.conf -.br -/etc/make.profile/make.defaults -.br -/etc/make.globals -.br -$PORTDIR/profiles/use.desc -.br -$PORTDIR/profiles/use.local.desc -.br - -.SH "AUTHOR" -Original version by Arun Bhanu <codebear@gentoo.org> -.br -Updated for rewritten euse by Marius Mauch <genone@gentoo.org> -.SH "BUGS" -euse doesn't handle USE flags enabled or disabled by use.defaults, use.mask -or package.use yet. It also doesn't completely understand the \-* flag. -.SH "SEE ALSO" -.BR ufed(8), -.TP -The \fI/usr/bin/euse\fR script. diff --git a/src/gentoolkit/AUTHORS b/src/gentoolkit/AUTHORS deleted file mode 100644 index 0dfa694..0000000 --- a/src/gentoolkit/AUTHORS +++ /dev/null @@ -1,2 +0,0 @@ -Original author: -Karl Trygve Kalleberg <karltk@gentoo.org>
\ No newline at end of file diff --git a/src/gentoolkit/Makefile b/src/gentoolkit/Makefile deleted file mode 100644 index 831bcfd..0000000 --- a/src/gentoolkit/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2004 Karl Trygve Kalleberg <karltk@gentoo.org> -# Copyright 2004 Gentoo Technologies, Inc. -# Distributed under the terms of the GNU General Public License v2 -# -# $Header$ - -include ../../makedefs.mak - -all: - echo "LISTOWEL (n.) The small mat on the bar designed to be more absorbent than the bar, but not as absorbent as your elbows." - -dist: - mkdir -p ../../${distdir}/src/gentoolkit - cp Makefile AUTHORS README TODO errors.py package.py helpers.py pprinter.py __init__.py ../../${distdir}/src/gentoolkit/ - -install: - install -d $(docdir)/gentoolkit - install -m 0644 AUTHORS README TODO $(docdir)/gentoolkit/ - install -d $(DESTDIR)/usr/lib/gentoolkit/pym/gentoolkit - install -m 0644 package.py pprinter.py helpers.py errors.py $(DESTDIR)/usr/lib/gentoolkit/pym/gentoolkit/ - install -m 0644 __init__.py $(DESTDIR)/usr/lib/gentoolkit/pym/gentoolkit/ - diff --git a/src/gentoolkit/README b/src/gentoolkit/README deleted file mode 100644 index 916dc81..0000000 --- a/src/gentoolkit/README +++ /dev/null @@ -1,17 +0,0 @@ - -Package : gentoolkit -Version : see __init__.py -Author : See AUTHORS - -MOTIVATION - -This is the Python API for Gentoolkit. It contains common functionality shared -by the Gentoolkit tools written in Python. - -MECHANICS - -N/A - -IMPROVEMENTS - -N/A diff --git a/src/gentoolkit/TODO b/src/gentoolkit/TODO deleted file mode 100644 index e69de29..0000000 --- a/src/gentoolkit/TODO +++ /dev/null diff --git a/src/gentoolkit/__init__.py b/src/gentoolkit/__init__.py deleted file mode 100644 index 28b56be..0000000 --- a/src/gentoolkit/__init__.py +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/python -# -# Copyright 2003-2004 Karl Trygve Kalleberg -# Copyright 2003-2004 Gentoo Technologies, Inc. -# Distributed under the terms of the GNU General Public License v2 -# -# $Header$ -# Author: Karl Trygve Kalleberg <karltk@gentoo.org> -# -# Portions written ripped from -# - etcat, by Alistair Tse <liquidx@gentoo.org> -# - -__author__ = "Karl Trygve Kalleberg" -__email__ = "karltk@gentoo.org" -__version__ = "0.1.1" -__productname__ = "gentoolkit" -__description__ = "Gentoolkit Common Library" - -import os -import sys -try: - import portage -except ImportError: - sys.path.insert(0, "/usr/lib/portage/pym") - import portage -import re -try: - from threading import Lock -except ImportError: - # If we don't have thread support, we don't need to worry about - # locking the global settings object. So we define a "null" Lock. - class Lock: - def acquire(self): - pass - def release(self): - pass - -try: - import portage.exception as portage_exception -except ImportError: - import portage_exception - -try: - settingslock = Lock() - settings = portage.config(clone=portage.settings) - porttree = portage.db[portage.root]["porttree"] - vartree = portage.db[portage.root]["vartree"] - virtuals = portage.db[portage.root]["virtuals"] -except portage_exception.PermissionDenied, e: - sys.stderr.write("Permission denied: '%s'\n" % str(e)) - sys.exit(e.errno) - -Config = { - "verbosityLevel": 3 -} - -from helpers import * -from package import * diff --git a/src/gentoolkit/errors.py b/src/gentoolkit/errors.py deleted file mode 100644 index db81721..0000000 --- a/src/gentoolkit/errors.py +++ /dev/null @@ -1,14 +0,0 @@ -#! /usr/bin/python2 -# -# Copyright(c) 2004, Karl Trygve Kalleberg <karltk@gentoo.org> -# Copyright(c) 2004, Gentoo Foundation -# -# Licensed under the GNU General Public License, v2 -# -# $Header$ - -class FatalError: - def __init__(self, s): - self._message = s - def get_message(self): - return self._message
\ No newline at end of file diff --git a/src/gentoolkit/helpers.py b/src/gentoolkit/helpers.py deleted file mode 100644 index 4652b2d..0000000 --- a/src/gentoolkit/helpers.py +++ /dev/null @@ -1,162 +0,0 @@ -#!/usr/bin/python2 -# -# Copyright(c) 2004, Karl Trygve Kalleberg <karltk@gentoo.org> -# Copyright(c) 2004, Gentoo Foundation -# -# Licensed under the GNU General Public License, v2 -# -# $Header$ - -import portage -from gentoolkit import * -from package import * -from pprinter import print_warn -try: - from portage.util import unique_array -except ImportError: - from portage_util import unique_array - -def find_packages(search_key, masked=False): - """Returns a list of Package objects that matched the search key.""" - try: - if masked: - t = portage.db["/"]["porttree"].dbapi.xmatch("match-all", search_key) - t += portage.db["/"]["vartree"].dbapi.match(search_key) - else: - t = portage.db["/"]["porttree"].dbapi.match(search_key) - t += portage.db["/"]["vartree"].dbapi.match(search_key) - # catch the "amgigous package" Exception - except ValueError, e: - if isinstance(e[0],list): - t = [] - for cp in e[0]: - if masked: - t += portage.db["/"]["porttree"].dbapi.xmatch("match-all", cp) - t += portage.db["/"]["vartree"].dbapi.match(cp) - else: - t += portage.db["/"]["porttree"].dbapi.match(cp) - t += portage.db["/"]["vartree"].dbapi.match(cp) - else: - raise ValueError(e) - except portage_exception.InvalidAtom, e: - print_warn("Invalid Atom: '%s'" % str(e)) - return [] - # Make the list of packages unique - t = unique_array(t) - t.sort() - return [Package(x) for x in t] - -def find_installed_packages(search_key, masked=False): - """Returns a list of Package objects that matched the search key.""" - try: - t = portage.db["/"]["vartree"].dbapi.match(search_key) - # catch the "amgigous package" Exception - except ValueError, e: - if isinstance(e[0],list): - t = [] - for cp in e[0]: - t += portage.db["/"]["vartree"].dbapi.match(cp) - else: - raise ValueError(e) - except portage_exception.InvalidAtom, e: - print_warn("Invalid Atom: '%s'" % str(e)) - return [] - return [Package(x) for x in t] - -def find_best_match(search_key): - """Returns a Package object for the best available candidate that - matched the search key.""" - t = portage.db["/"]["porttree"].dep_bestmatch(search_key) - if t: - return Package(t) - return None - -def find_system_packages(prefilter=None): - """Returns a tuple of lists, first list is resolved system packages, - second is a list of unresolved packages.""" - pkglist = settings.packages - resolved = [] - unresolved = [] - for x in pkglist: - cpv = x.strip() - if len(cpv) and cpv[0] == "*": - pkg = find_best_match(cpv) - if pkg: - resolved.append(pkg) - else: - unresolved.append(cpv) - return (resolved, unresolved) - -def find_world_packages(prefilter=None): - """Returns a tuple of lists, first list is resolved world packages, - seond is unresolved package names.""" - f = open(portage.root+portage.WORLD_FILE) - pkglist = f.readlines() - resolved = [] - unresolved = [] - for x in pkglist: - cpv = x.strip() - if len(cpv) and cpv[0] != "#": - pkg = find_best_match(cpv) - if pkg: - resolved.append(pkg) - else: - unresolved.append(cpv) - return (resolved,unresolved) - -def find_all_installed_packages(prefilter=None): - """Returns a list of all installed packages, after applying the prefilter - function""" - t = vartree.dbapi.cpv_all() - if prefilter: - t = filter(prefilter,t) - return [Package(x) for x in t] - -def find_all_uninstalled_packages(prefilter=None): - """Returns a list of all uninstalled packages, after applying the prefilter - function""" - alist = find_all_packages(prefilter) - return [x for x in alist if not x.is_installed()] - -def find_all_packages(prefilter=None): - """Returns a list of all known packages, installed or not, after applying - the prefilter function""" - t = porttree.dbapi.cp_all() - t += vartree.dbapi.cp_all() - if prefilter: - t = filter(prefilter,t) - t = unique_array(t) - t2 = [] - for x in t: - t2 += porttree.dbapi.cp_list(x) - t2 += vartree.dbapi.cp_list(x) - t2 = unique_array(t2) - return [Package(x) for x in t2] - -def split_package_name(name): - """Returns a list on the form [category, name, version, revision]. Revision will - be 'r0' if none can be inferred. Category and version will be empty, if none can - be inferred.""" - r = portage.catpkgsplit(name) - if not r: - r = name.split("/") - if len(r) == 1: - return ["", name, "", "r0"] - else: - return r + ["", "r0"] - else: - r = list(r) - if r[0] == 'null': - r[0] = '' - return r - -def sort_package_list(pkglist): - """Returns the list ordered in the same way portage would do with lowest version - at the head of the list.""" - pkglist.sort(Package.compare_version) - return pkglist - -if __name__ == "__main__": - print "This module is for import only" - - diff --git a/src/gentoolkit/package.py b/src/gentoolkit/package.py deleted file mode 100644 index 4f28671..0000000 --- a/src/gentoolkit/package.py +++ /dev/null @@ -1,243 +0,0 @@ -#! /usr/bin/python2 -# -# Copyright(c) 2004, Karl Trygve Kalleberg <karltk@gentoo.org> -# Copyright(c) 2004, Gentoo Foundation -# -# Licensed under the GNU General Public License, v2 -# -# $Header$ - -import os -from errors import FatalError -import portage -from gentoolkit import * - -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) - - if not self._scpv: - raise FatalError("invalid cpv: %s" % cpv) - self._db = None - self._settings = settings - self._settingslock = settingslock - self._portdir_path = os.path.realpath(settings["PORTDIR"]) - - 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_settings(self, key): - """Returns the value of the given key for this package (useful - for package.* files.""" - self._settingslock.acquire() - self._settings.setcpv(self._cpv) - v = self._settings[key] - self._settingslock.release() - return v - - def get_cpv(self): - """Returns full Category/Package-Version string""" - return self._cpv - - def get_provide(self): - """Return a list of provides, if any""" - if not self.is_installed(): - try: - x = [self.get_env_var('PROVIDE')] - except KeyError: - x = [] - return x - else: - return vartree.get_provide(self._cpv) - - def get_dependants(self): - """Retrieves a list of CPVs for all packages depending on this one""" - raise NotImplementedError("Not implemented yet!") - - def get_runtime_deps(self): - """Returns a linearised list of first-level run time dependencies for this package, on - the form [(comparator, [use flags], cpv), ...]""" - # Try to use the portage tree first, since emerge only uses the tree when calculating dependencies - try: - cd = self.get_env_var("RDEPEND", porttree).split() - except KeyError: - cd = self.get_env_var("RDEPEND", vartree).split() - r,i = self._parse_deps(cd) - return r - - def get_compiletime_deps(self): - """Returns a linearised list of first-level compile time dependencies for this package, on - the form [(comparator, [use flags], cpv), ...]""" - # Try to use the portage tree first, since emerge only uses the tree when calculating dependencies - try: - rd = self.get_env_var("DEPEND", porttree).split() - except KeyError: - rd = self.get_env_var("DEPEND", vartree).split() - r,i = self._parse_deps(rd) - return r - - def get_postmerge_deps(self): - """Returns a linearised list of first-level post merge dependencies for this package, on - the form [(comparator, [use flags], cpv), ...]""" - # Try to use the portage tree first, since emerge only uses the tree when calculating dependencies - try: - pd = self.get_env_var("PDEPEND", porttree).split() - except KeyError: - pd = self.get_env_var("PDEPEND", vartree).split() - r,i = self._parse_deps(pd) - return r - - def _parse_deps(self,deps,curuse=[],level=0): - # store (comparator, [use predicates], cpv) - r = [] - comparators = ["~","<",">","=","<=",">="] - end = len(deps) - i = 0 - while i < end: - tok = deps[i] - if tok == ')': - return r,i - if tok[-1] == "?": - tok = tok.replace("?","") - sr,l = self._parse_deps(deps[i+2:],curuse=curuse+[tok],level=level+1) - r += sr - i += l + 3 - continue - if tok == "||": - sr,l = self._parse_deps(deps[i+2:],curuse,level=level+1) - r += sr - i += l + 3 - continue - # conjonction, like in "|| ( ( foo bar ) baz )" => recurse - if tok == "(": - sr,l = self._parse_deps(deps[i+1:],curuse,level=level+1) - r += sr - i += l + 2 - continue - # pkg block "!foo/bar" => ignore it - if tok[0] == "!": - i += 1 - continue - # pick out comparator, if any - cmp = "" - for c in comparators: - if tok.find(c) == 0: - cmp = c - tok = tok[len(cmp):] - r.append((cmp,curuse,tok)) - i += 1 - return r,i - - def is_installed(self): - """Returns true if this package is installed (merged)""" - self._initdb() - return os.path.exists(self._db.getpath()) - - def is_overlay(self): - """Returns true if the package is in an overlay.""" - dir,ovl = portage.portdb.findname2(self._cpv) - return ovl != self._portdir_path - - 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._cpv) - return self._cpv not in unmasked - - def get_ebuild_path(self,in_vartree=0): - """Returns the complete path to the .ebuild file""" - if in_vartree: - return vartree.getebuildpath(self._cpv) - else: - return portage.portdb.findname(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 "/".join(sp[:-1]) - - def get_env_var(self, var, tree=""): - """Returns one of the predefined env vars DEPEND, RDEPEND, SRC_URI,....""" - if tree == "": - mytree = vartree - if not self.is_installed(): - mytree = porttree - else: - mytree = tree - r = mytree.dbapi.aux_get(self._cpv,[var]) - if not r: - raise FatalError("Could not find the package tree") - if len(r) != 1: - raise FatalError("Should only get one element!") - return r[0] - - def get_use_flags(self): - """Returns the USE flags active at time of installation""" - self._initdb() - if self.is_installed(): - return self._db.getfile("USE") - return "" - - 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.get_cpv()) - # if category is different - if v1[0] != v2[0]: - return cmp(v1[0],v2[0]) - # if name is different - elif v1[1] != v2[1]: - return cmp(v1[1],v2[1]) - # Compare versions - else: - return portage.pkgcmp(v1[1:],v2[1:]) - - def size(self): - """Estimates the installed size of the contents of this package, if possible. - Returns [size, number of files in total, number of uncounted files]""" - contents = self.get_contents() - size = 0 - uncounted = 0 - files = 0 - for x in contents: - try: - size += os.lstat(x).st_size - files += 1 - except OSError: - uncounted += 1 - return [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,settings["ROOT"],settings) diff --git a/src/gentoolkit/pprinter.py b/src/gentoolkit/pprinter.py deleted file mode 100644 index ff92a26..0000000 --- a/src/gentoolkit/pprinter.py +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/python -# -# Copyright 2004 Karl Trygve Kalleberg <karltk@gentoo.org> -# Copyright 2004 Gentoo Foundation -# Distributed under the terms of the GNU General Public License v2 -# -# $Header$ - -import sys -import gentoolkit - -try: - import portage.output as output -except ImportError: - import output - - -def print_error(s): - """Prints an error string to stderr.""" - sys.stderr.write(output.red("!!! ") + s + "\n") - -def print_info(lv, s, line_break = True): - """Prints an informational string to stdout.""" - if gentoolkit.Config["verbosityLevel"] >= lv: - sys.stdout.write(s) - if line_break: - sys.stdout.write("\n") - -def print_warn(s): - """Print a warning string to stderr.""" - sys.stderr.write("!!! " + s + "\n") - -def die(err, s): - """Print an error string and die with an error code.""" - print_error(s) - sys.exit(err) - -# Colour settings - -def cpv(s): - """Print a category/package-<version> string.""" - return output.green(s) - -def slot(s): - """Print a slot string""" - return output.bold(s) - -def useflag(s): - """Print a USE flag strign""" - return output.blue(s) - -def useflagon(s): - """Print an enabled USE flag string""" - # FIXME: Collapse into useflag with parameter - return output.red(s) - -def useflagoff(s): - """Print a disabled USE flag string""" - # FIXME: Collapse into useflag with parameter - return output.blue(s) - -def maskflag(s): - """Print a masking flag string""" - return output.red(s) - -def installedflag(s): - """Print an installed flag string""" - return output.bold(s) - -def number(s): - """Print a number string""" - return output.turquoise(s) - -def pkgquery(s): - """Print a package query string.""" - return output.bold(s) - -def regexpquery(s): - """Print a regular expression string""" - return output.bold(s) - -def path(s): - """Print a file or directory path string""" - return output.bold(s) - -def path_symlink(s): - """Print a symlink string.""" - return output.turquoise(s) - -def productname(s): - """Print a product name string, i.e. the program name.""" - return output.turquoise(s) - -def globaloption(s): - """Print a global option string, i.e. the program global options.""" - return output.yellow(s) - -def localoption(s): - """Print a local option string, i.e. the program local options.""" - return output.green(s) - -def command(s): - """Print a program command string.""" - return output.green(s) - -def section(s): - """Print a string as a section header.""" - return output.turquoise(s) - -def subsection(s): - """Print a string as a subsection header.""" - return output.turquoise(s) - -def emph(s): - """Print a string as emphasized.""" - return output.bold(s) diff --git a/src/glsa-check/Makefile b/src/glsa-check/Makefile deleted file mode 100644 index 9ad5717..0000000 --- a/src/glsa-check/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright 2003 Karl Trygve Kalleberg <karltk@gentoo.org> -# Copyright 2003 Gentoo Technologies, Inc. -# Distributed under the terms of the GNU General Public License v2 -# -# $Header$ - -include ../../makedefs.mak - -all: - echo "YADDLETHORPE (vb.) (Of offended pooves.) To exit huffily from a boutique." - -dist: - mkdir -p ../../$(distdir)/src/glsa-check/ - cp Makefile glsa.py glsa-check glsa-check.1 ../../$(distdir)/src/glsa-check/ - -install: - install -d $(DESTDIR)/usr/lib/gentoolkit/pym/ - install -m 0755 glsa-check $(bindir)/ - install -m 0644 glsa.py $(DESTDIR)/usr/lib/gentoolkit/pym/ - install -m 0644 glsa-check.1 $(mandir)/ diff --git a/src/glsa-check/glsa-check b/src/glsa-check/glsa-check deleted file mode 100755 index fe38331..0000000 --- a/src/glsa-check/glsa-check +++ /dev/null @@ -1,371 +0,0 @@ -#!/usr/bin/python - -# $Header: $ -# This program is licensed under the GPL, version 2 - -import os -import sys -sys.path.insert(0, "/usr/lib/gentoolkit/pym") -try: - import portage -except ImportError: - sys.path.insert(0, "/usr/lib/portage/pym") - import portage - -try: - from portage.output import * -except ImportError: - from output import * - -from getopt import getopt, GetoptError - -__program__ = "glsa-check" -__author__ = "Marius Mauch <genone@gentoo.org>" -__version__ = "0.9" - -optionmap = [ -["-l", "--list", "list all unapplied GLSA"], -["-d", "--dump", "--print", "show all information about the given GLSA"], -["-t", "--test", "test if this system is affected by the given GLSA"], -["-p", "--pretend", "show the necessary commands to apply this GLSA"], -["-f", "--fix", "try to auto-apply this GLSA (experimental)"], -["-i", "--inject", "inject the given GLSA into the checkfile"], -["-n", "--nocolor", "disable colors (option)"], -["-e", "--emergelike", "do not use a least-change algorithm (option)"], -["-h", "--help", "show this help message"], -["-V", "--version", "some information about this tool"], -["-v", "--verbose", "print more information (option)"], -["-c", "--cve", "show CAN ids in listing mode (option)"], -["-m", "--mail", "send a mail with the given GLSAs to the administrator"] -] - -# print a warning as this is beta code (but proven by now, so no more warning) -#sys.stderr.write("WARNING: This tool is completely new and not very tested, so it should not be\n") -#sys.stderr.write("used on production systems. It's mainly a test tool for the new GLSA release\n") -#sys.stderr.write("and distribution system, it's functionality will later be merged into emerge\n") -#sys.stderr.write("and equery.\n") -#sys.stderr.write("Please read http://www.gentoo.org/proj/en/portage/glsa-integration.xml\n") -#sys.stderr.write("before using this tool AND before reporting a bug.\n\n") - -# option parsing -args = [] -params = [] -try: - args, params = getopt(sys.argv[1:], "".join([o[0][1] for o in optionmap]), \ - [x[2:] for x in reduce(lambda x,y: x+y, [z[1:-1] for z in optionmap])]) -# ["dump", "print", "list", "pretend", "fix", "inject", "help", "verbose", "version", "test", "nocolor", "cve", "mail"]) - args = [a for a,b in args] - - for option in ["--nocolor", "-n"]: - if option in args: - nocolor() - args.remove(option) - - verbose = False - for option in ["--verbose", "-v"]: - if option in args: - verbose = True - args.remove(option) - - list_cve = False - for option in ["--cve", "-c"]: - if option in args: - list_cve = True - args.remove(option) - - least_change = True - for option in ["--emergelike", "-e"]: - if option in args: - least_change = False - args.remove(option) - - # sanity checking - if len(args) <= 0: - sys.stderr.write("no option given: what should I do ?\n") - mode = "HELP" - elif len(args) > 1: - sys.stderr.write("please use only one command per call\n") - mode = "HELP" - else: - # in what mode are we ? - args = args[0] - for m in optionmap: - if args in [o for o in m[:-1]]: - mode = m[1][2:] - -except GetoptError, e: - sys.stderr.write("unknown option given: ") - sys.stderr.write(str(e)+"\n") - mode = "HELP" - -# we need a set of glsa for most operation modes -if len(params) <= 0 and mode in ["fix", "test", "pretend", "dump", "inject", "mail"]: - sys.stderr.write("\nno GLSA given, so we'll do nothing for now. \n") - sys.stderr.write("If you want to run on all GLSA please tell me so \n") - sys.stderr.write("(specify \"all\" as parameter)\n\n") - mode = "HELP" -elif len(params) <= 0 and mode == "list": - params.append("new") - -# show help message -if mode == "help" or mode == "HELP": - msg = "Syntax: glsa-check <option> [glsa-list]\n\n" - for m in optionmap: - msg += m[0] + "\t" + m[1] + " \t: " + m[-1] + "\n" - for o in m[2:-1]: - msg += "\t" + o + "\n" - msg += "\nglsa-list can contain an arbitrary number of GLSA ids, \n" - msg += "filenames containing GLSAs or the special identifiers \n" - msg += "'all', 'new' and 'affected'\n" - if mode == "help": - sys.stdout.write(msg) - sys.exit(0) - else: - sys.stderr.write("\n" + msg) - sys.exit(1) - -# we need root priviledges for write access -if mode in ["fix", "inject"] and os.geteuid() != 0: - sys.stderr.write(__program__ + ": root access is needed for \""+mode+"\" mode\n") - sys.exit(2) - -# show version and copyright information -if mode == "version": - sys.stderr.write("\n"+ __program__ + ", version " + __version__ + "\n") - sys.stderr.write("Author: " + __author__ + "\n") - sys.stderr.write("This program is licensed under the GPL, version 2\n\n") - sys.exit(0) - -# delay this for speed increase -from glsa import * - -glsaconfig = checkconfig(portage.config(clone=portage.settings)) - -vardb = portage.db["/"]["vartree"].dbapi -portdb = portage.db["/"]["porttree"].dbapi - -# Check that we really have a glsa dir to work on -if not (os.path.exists(glsaconfig["GLSA_DIR"]) and os.path.isdir(glsaconfig["GLSA_DIR"])): - sys.stderr.write(red("ERROR")+": GLSA_DIR %s doesn't exist. Please fix this.\n" % glsaconfig["GLSA_DIR"]) - sys.exit(1) - -# build glsa lists -completelist = get_glsa_list(glsaconfig["GLSA_DIR"], glsaconfig) - -if os.access(glsaconfig["CHECKFILE"], os.R_OK): - checklist = [line.strip() for line in open(glsaconfig["CHECKFILE"], "r").readlines()] -else: - checklist = [] -todolist = [e for e in completelist if e not in checklist] - -glsalist = [] -if "new" in params: - glsalist = todolist - params.remove("new") - -if "all" in params: - glsalist = completelist - params.remove("all") -if "affected" in params: - # replaced completelist with todolist on request of wschlich - for x in todolist: - try: - myglsa = Glsa(x, glsaconfig) - except (GlsaTypeException, GlsaFormatException), e: - if verbose: - sys.stderr.write(("invalid GLSA: %s (error message was: %s)\n" % (x, e))) - continue - if myglsa.isVulnerable(): - glsalist.append(x) - params.remove("affected") - -# remove invalid parameters -for p in params[:]: - if not (p in completelist or os.path.exists(p)): - sys.stderr.write(("(removing %s from parameter list as it isn't a valid GLSA specification)\n" % p)) - params.remove(p) - -glsalist.extend([g for g in params if g not in glsalist]) - -def summarylist(myglsalist, fd1=sys.stdout, fd2=sys.stderr): - fd2.write(white("[A]")+" means this GLSA was already applied,\n") - fd2.write(green("[U]")+" means the system is not affected and\n") - fd2.write(red("[N]")+" indicates that the system might be affected.\n\n") - - for myid in myglsalist: - try: - myglsa = Glsa(myid, glsaconfig) - except (GlsaTypeException, GlsaFormatException), e: - if verbose: - fd2.write(("invalid GLSA: %s (error message was: %s)\n" % (myid, e))) - continue - if myglsa.isApplied(): - status = "[A]" - color = white - elif myglsa.isVulnerable(): - status = "[N]" - color = red - else: - status = "[U]" - color = green - - if verbose: - access = ("[%-8s] " % myglsa.access) - else: - access="" - - fd1.write(color(myglsa.nr) + " " + color(status) + " " + color(access) + myglsa.title + " (") - if not verbose: - for pkg in myglsa.packages.keys()[:3]: - fd1.write(" " + pkg + " ") - if len(myglsa.packages) > 3: - fd1.write("... ") - else: - for pkg in myglsa.packages.keys(): - mylist = vardb.match(portage.dep_getkey(str(pkg))) - if len(mylist) > 0: - pkg = color(" ".join(mylist)) - fd1.write(" " + pkg + " ") - - fd1.write(")") - if list_cve: - fd1.write(" "+(",".join([r[:13] for r in myglsa.references if r[:4] in ["CAN-", "CVE-"]]))) - fd1.write("\n") - return 0 - -if mode == "list": - sys.exit(summarylist(glsalist)) - -# dump, fix, inject and fix are nearly the same code, only the glsa method call differs -if mode in ["dump", "fix", "inject", "pretend"]: - for myid in glsalist: - try: - myglsa = Glsa(myid, glsaconfig) - except (GlsaTypeException, GlsaFormatException), e: - if verbose: - sys.stderr.write(("invalid GLSA: %s (error message was: %s)\n" % (myid, e))) - continue - if mode == "dump": - myglsa.dump() - elif mode == "fix": - sys.stdout.write("fixing "+myid+"\n") - mergelist = myglsa.getMergeList(least_change=least_change) - for pkg in mergelist: - sys.stdout.write(">>> merging "+pkg+"\n") - # using emerge for the actual merging as it contains the dependency - # code and we want to be consistent in behaviour. Also this functionality - # will be integrated in emerge later, so it shouldn't hurt much. - emergecmd = "emerge --oneshot " + glsaconfig["EMERGE_OPTS"] + " =" + pkg - if verbose: - sys.stderr.write(emergecmd+"\n") - exitcode = os.system(emergecmd) - # system() returns the exitcode in the high byte of a 16bit integer - if exitcode >= 1<<8: - exitcode >>= 8 - if exitcode: - sys.exit(exitcode) - if len(mergelist): - sys.stdout.write("\n") - myglsa.inject() - elif mode == "pretend": - sys.stdout.write("Checking GLSA "+myid+"\n") - mergelist = myglsa.getMergeList(least_change=least_change) - if mergelist: - sys.stdout.write("The following updates will be performed for this GLSA:\n") - for pkg in mergelist: - oldver = None - for x in vardb.match(portage.dep_getkey(pkg)): - if vardb.aux_get(x, ["SLOT"]) == portdb.aux_get(pkg, ["SLOT"]): - oldver = x - if oldver == None: - raise ValueError("could not find old version for package %s" % pkg) - oldver = oldver[len(portage.dep_getkey(oldver))+1:] - sys.stdout.write(" " + pkg + " (" + oldver + ")\n") - else: - sys.stdout.write("Nothing to do for this GLSA\n") - sys.stdout.write("\n") - elif mode == "inject": - sys.stdout.write("injecting " + myid + "\n") - myglsa.inject() - sys.exit(0) - -# test is a bit different as Glsa.test() produces no output -if mode == "test": - outputlist = [] - for myid in glsalist: - try: - myglsa = Glsa(myid, glsaconfig) - except (GlsaTypeException, GlsaFormatException), e: - if verbose: - sys.stderr.write(("invalid GLSA: %s (error message was: %s)\n" % (myid, e))) - continue - if myglsa.isVulnerable(): - if verbose: - outputlist.append(str(myglsa.nr)+" ( "+myglsa.title+" ) ") - else: - outputlist.append(str(myglsa.nr)) - if len(outputlist) > 0: - sys.stderr.write("This system is affected by the following GLSAs:\n") - sys.stdout.write("\n".join(outputlist)+"\n") - else: - sys.stderr.write("This system is not affected by any of the listed GLSAs\n") - sys.exit(0) - -# mail mode as requested by solar -if mode == "mail": - try: - import portage.mail as portage_mail - except ImportError: - import portage_mail - - import socket - from StringIO import StringIO - try: - from email.mime.text import MIMEText - except ImportError: - from email.MIMEText import MIMEText - - # color doesn't make any sense for mail - nocolor() - - if "PORTAGE_ELOG_MAILURI" in glsaconfig: - myrecipient = glsaconfig["PORTAGE_ELOG_MAILURI"].split()[0] - else: - myrecipient = "root@localhost" - - if "PORTAGE_ELOG_MAILFROM" in glsaconfig: - myfrom = glsaconfig["PORTAGE_ELOG_MAILFROM"] - else: - myfrom = "glsa-check" - - mysubject = "[glsa-check] Summary for %s" % socket.getfqdn() - - # need a file object for summarylist() - myfd = StringIO() - myfd.write("GLSA Summary report for host %s\n" % socket.getfqdn()) - myfd.write("(Command was: %s)\n\n" % " ".join(sys.argv)) - summarylist(glsalist, fd1=myfd, fd2=myfd) - summary = str(myfd.getvalue()) - myfd.close() - - myattachments = [] - for myid in glsalist: - try: - myglsa = Glsa(myid, glsaconfig) - except (GlsaTypeException, GlsaFormatException), e: - if verbose: - sys.stderr.write(("invalid GLSA: %s (error message was: %s)\n" % (myid, e))) - continue - myfd = StringIO() - myglsa.dump(outstream=myfd) - myattachments.append(MIMEText(str(myfd.getvalue()), _charset="utf8")) - myfd.close() - - mymessage = portage_mail.create_message(myfrom, myrecipient, mysubject, summary, myattachments) - portage_mail.send_mail(glsaconfig, mymessage) - - sys.exit(0) - -# something wrong here, all valid paths are covered with sys.exit() -sys.stderr.write("nothing more to do\n") -sys.exit(2) diff --git a/src/glsa-check/glsa-check.1 b/src/glsa-check/glsa-check.1 deleted file mode 100644 index 8e0df42..0000000 --- a/src/glsa-check/glsa-check.1 +++ /dev/null @@ -1,57 +0,0 @@ -.TH "glsa-check" "1" "0.6" "Marius Mauch" "gentoolkit" -.SH "NAME" -.LP -glsa\-check \- Gentoo: Tool to locally monitor and manage GLSA's -.SH "SYNTAX" -.LP -glsa\-check <\fIoption\fP> [\fIglsa\-list\fP] - -[\fIglsa\-list\fR] can contain an arbitrary number of GLSA ids, filenames containing GLSAs or the special identifiers 'all', 'new' and 'affected' -.SH "DESCRIPTION" -.LP -This tool is used to locally monitor and manage Gentoo Linux Security Advisories. -Please read: -.br -http://www.gentoo.org/security -.br -before reporting a bug. -.LP -Note: In order for this tool to be effective, you must regularly sync your local portage tree. -.SH "OPTIONS" -.LP -.TP -.B \-l, \-\-list -list all unapplied GLSA -.TP -.B \-d, \-\-dump, \-\-print -show all information about the given GLSA -.TP -.B \-t, \-\-test -test if this system is affected by the given GLSA -.TP -.B \-p, \-\-pretend -show the necessary commands to apply this GLSA -.TP -.B \-f, \-\-fix -try to auto\-apply this GLSA (experimental) -.TP -.B \-i, \-\-inject -inject the given GLSA into the checkfile -.TP -.B \-n, \-\-nocolor -disable colors (option) -.TP -.B \-h, \-\-help -show this help message -.TP -.B \-V, \-\-version -some information about this tool -.TP -.B \-v, \-\-verbose -print more messages (option) -.TP -.B \-c, \-\-cve -show CAN ids in listing mode (option) -.TP -.B \-m, \-\-mail -send a mail with the given GLSAs to the administrator diff --git a/src/glsa-check/glsa.py b/src/glsa-check/glsa.py deleted file mode 100644 index dfd9acd..0000000 --- a/src/glsa-check/glsa.py +++ /dev/null @@ -1,644 +0,0 @@ -# $Header$ - -# This program is licensed under the GPL, version 2 - -# WARNING: this code is only tested by a few people and should NOT be used -# on production systems at this stage. There are possible security holes and probably -# bugs in this code. If you test it please report ANY success or failure to -# me (genone@gentoo.org). - -# The following planned features are currently on hold: -# - getting GLSAs from http/ftp servers (not really useful without the fixed ebuilds) -# - GPG signing/verification (until key policy is clear) - -__author__ = "Marius Mauch <genone@gentoo.org>" - -import os -import sys -import urllib -import time -import codecs -import re -import xml.dom.minidom - -if sys.version_info[0:2] < (2, 3): - raise NotImplementedError("Python versions below 2.3 have broken XML code " \ - +"and are not supported") - -try: - import portage -except ImportError: - sys.path.insert(0, "/usr/lib/portage/pym") - import portage - -# Note: the space for rgt and rlt is important !! -opMapping = {"le": "<=", "lt": "<", "eq": "=", "gt": ">", "ge": ">=", - "rge": ">=~", "rle": "<=~", "rgt": " >~", "rlt": " <~"} -NEWLINE_ESCAPE = "!;\\n" # some random string to mark newlines that should be preserved -SPACE_ESCAPE = "!;_" # some random string to mark spaces that should be preserved - -def center(text, width): - """ - Returns a string containing I{text} that is padded with spaces on both - sides. If C{len(text) >= width} I{text} is returned unchanged. - - @type text: String - @param text: the text to be embedded - @type width: Integer - @param width: the minimum length of the returned string - @rtype: String - @return: the expanded string or I{text} - """ - if len(text) >= width: - return text - margin = (width-len(text))/2 - rValue = " "*margin - rValue += text - if 2*margin + len(text) == width: - rValue += " "*margin - elif 2*margin + len(text) + 1 == width: - rValue += " "*(margin+1) - return rValue - - -def wrap(text, width, caption=""): - """ - Wraps the given text at column I{width}, optionally indenting - it so that no text is under I{caption}. It's possible to encode - hard linebreaks in I{text} with L{NEWLINE_ESCAPE}. - - @type text: String - @param text: the text to be wrapped - @type width: Integer - @param width: the column at which the text should be wrapped - @type caption: String - @param caption: this string is inserted at the beginning of the - return value and the paragraph is indented up to - C{len(caption)}. - @rtype: String - @return: the wrapped and indented paragraph - """ - rValue = "" - line = caption - text = text.replace(2*NEWLINE_ESCAPE, NEWLINE_ESCAPE+" "+NEWLINE_ESCAPE) - words = text.split() - indentLevel = len(caption)+1 - - for w in words: - if line[-1] == "\n": - rValue += line - line = " "*indentLevel - if len(line)+len(w.replace(NEWLINE_ESCAPE, ""))+1 > width: - rValue += line+"\n" - line = " "*indentLevel+w.replace(NEWLINE_ESCAPE, "\n") - elif w.find(NEWLINE_ESCAPE) >= 0: - if len(line.strip()) > 0: - rValue += line+" "+w.replace(NEWLINE_ESCAPE, "\n") - else: - rValue += line+w.replace(NEWLINE_ESCAPE, "\n") - line = " "*indentLevel - else: - if len(line.strip()) > 0: - line += " "+w - else: - line += w - if len(line) > 0: - rValue += line.replace(NEWLINE_ESCAPE, "\n") - rValue = rValue.replace(SPACE_ESCAPE, " ") - return rValue - -def checkconfig(myconfig): - """ - takes a portage.config instance and adds GLSA specific keys if - they are not present. TO-BE-REMOVED (should end up in make.*) - """ - mysettings = { - "GLSA_DIR": portage.settings["PORTDIR"]+"/metadata/glsa/", - "GLSA_PREFIX": "glsa-", - "GLSA_SUFFIX": ".xml", - "CHECKFILE": "/var/cache/edb/glsa", - "GLSA_SERVER": "www.gentoo.org/security/en/glsa/", # not completely implemented yet - "CHECKMODE": "local", # not completely implemented yet - "PRINTWIDTH": "76" - } - for k in mysettings.keys(): - if k not in myconfig: - myconfig[k] = mysettings[k] - return myconfig - -def get_glsa_list(repository, myconfig): - """ - Returns a list of all available GLSAs in the given repository - by comparing the filelist there with the pattern described in - the config. - - @type repository: String - @param repository: The directory or an URL that contains GLSA files - (Note: not implemented yet) - @type myconfig: portage.config - @param myconfig: a GLSA aware config instance (see L{checkconfig}) - - @rtype: List of Strings - @return: a list of GLSA IDs in this repository - """ - # TODO: remote fetch code for listing - - rValue = [] - - if not os.access(repository, os.R_OK): - return [] - dirlist = os.listdir(repository) - prefix = myconfig["GLSA_PREFIX"] - suffix = myconfig["GLSA_SUFFIX"] - - for f in dirlist: - try: - if f[:len(prefix)] == prefix: - rValue.append(f[len(prefix):-1*len(suffix)]) - except IndexError: - pass - return rValue - -def getListElements(listnode): - """ - Get all <li> elements for a given <ol> or <ul> node. - - @type listnode: xml.dom.Node - @param listnode: <ul> or <ol> list to get the elements for - @rtype: List of Strings - @return: a list that contains the value of the <li> elements - """ - rValue = [] - if not listnode.nodeName in ["ul", "ol"]: - raise GlsaFormatException("Invalid function call: listnode is not <ul> or <ol>") - for li in listnode.childNodes: - if li.nodeType != xml.dom.Node.ELEMENT_NODE: - continue - rValue.append(getText(li, format="strip")) - return rValue - -def getText(node, format): - """ - This is the main parser function. It takes a node and traverses - recursive over the subnodes, getting the text of each (and the - I{link} attribute for <uri> and <mail>). Depending on the I{format} - parameter the text might be formatted by adding/removing newlines, - tabs and spaces. This function is only useful for the GLSA DTD, - it's not applicable for other DTDs. - - @type node: xml.dom.Node - @param node: the root node to start with the parsing - @type format: String - @param format: this should be either I{strip}, I{keep} or I{xml} - I{keep} just gets the text and does no formatting. - I{strip} replaces newlines and tabs with spaces and - replaces multiple spaces with one space. - I{xml} does some more formatting, depending on the - type of the encountered nodes. - @rtype: String - @return: the (formatted) content of the node and its subnodes - """ - rValue = "" - if format in ["strip", "keep"]: - if node.nodeName in ["uri", "mail"]: - rValue += node.childNodes[0].data+": "+node.getAttribute("link") - else: - for subnode in node.childNodes: - if subnode.nodeName == "#text": - rValue += subnode.data - else: - rValue += getText(subnode, format) - else: - for subnode in node.childNodes: - if subnode.nodeName == "p": - for p_subnode in subnode.childNodes: - if p_subnode.nodeName == "#text": - rValue += p_subnode.data.strip() - elif p_subnode.nodeName in ["uri", "mail"]: - rValue += p_subnode.childNodes[0].data - rValue += " ( "+p_subnode.getAttribute("link")+" )" - rValue += NEWLINE_ESCAPE - elif subnode.nodeName == "ul": - for li in getListElements(subnode): - rValue += "-"+SPACE_ESCAPE+li+NEWLINE_ESCAPE+" " - elif subnode.nodeName == "ol": - i = 0 - for li in getListElements(subnode): - i = i+1 - rValue += str(i)+"."+SPACE_ESCAPE+li+NEWLINE_ESCAPE+" " - elif subnode.nodeName == "code": - rValue += getText(subnode, format="keep").replace("\n", NEWLINE_ESCAPE) - if rValue[-1*len(NEWLINE_ESCAPE):] != NEWLINE_ESCAPE: - rValue += NEWLINE_ESCAPE - elif subnode.nodeName == "#text": - rValue += subnode.data - else: - raise GlsaFormatException("Invalid Tag found: ", subnode.nodeName) - if format == "strip": - rValue = rValue.strip(" \n\t") - rValue = re.sub("[\s]{2,}", " ", rValue) - # Hope that the utf conversion doesn't break anything else - return rValue.encode("utf_8") - -def getMultiTagsText(rootnode, tagname, format): - """ - Returns a list with the text of all subnodes of type I{tagname} - under I{rootnode} (which itself is not parsed) using the given I{format}. - - @type rootnode: xml.dom.Node - @param rootnode: the node to search for I{tagname} - @type tagname: String - @param tagname: the name of the tags to search for - @type format: String - @param format: see L{getText} - @rtype: List of Strings - @return: a list containing the text of all I{tagname} childnodes - """ - rValue = [] - for e in rootnode.getElementsByTagName(tagname): - rValue.append(getText(e, format)) - return rValue - -def makeAtom(pkgname, versionNode): - """ - creates from the given package name and information in the - I{versionNode} a (syntactical) valid portage atom. - - @type pkgname: String - @param pkgname: the name of the package for this atom - @type versionNode: xml.dom.Node - @param versionNode: a <vulnerable> or <unaffected> Node that - contains the version information for this atom - @rtype: String - @return: the portage atom - """ - rValue = opMapping[versionNode.getAttribute("range")] \ - + pkgname \ - + "-" + getText(versionNode, format="strip") - return str(rValue) - -def makeVersion(versionNode): - """ - creates from the information in the I{versionNode} a - version string (format <op><version>). - - @type versionNode: xml.dom.Node - @param versionNode: a <vulnerable> or <unaffected> Node that - contains the version information for this atom - @rtype: String - @return: the version string - """ - return opMapping[versionNode.getAttribute("range")] \ - +getText(versionNode, format="strip") - -def match(atom, portdbname, match_type="default"): - """ - wrapper that calls revisionMatch() or portage.dbapi.match() depending on - the given atom. - - @type atom: string - @param atom: a <~ or >~ atom or a normal portage atom that contains the atom to match against - @type portdb: portage.dbapi - @param portdb: one of the portage databases to use as information source - @type match_type: string - @param match_type: if != "default" passed as first argument to dbapi.xmatch - to apply the wanted visibility filters - - @rtype: list of strings - @return: a list with the matching versions - """ - db = portage.db["/"][portdbname].dbapi - if atom[2] == "~": - return revisionMatch(atom, db, match_type=match_type) - elif match_type == "default" or not hasattr(db, "xmatch"): - return db.match(atom) - else: - return db.xmatch(match_type, atom) - -def revisionMatch(revisionAtom, portdb, match_type="default"): - """ - handler for the special >~, >=~, <=~ and <~ atoms that are supposed to behave - as > and < except that they are limited to the same version, the range only - applies to the revision part. - - @type revisionAtom: string - @param revisionAtom: a <~ or >~ atom that contains the atom to match against - @type portdb: portage.dbapi - @param portdb: one of the portage databases to use as information source - @type match_type: string - @param match_type: if != "default" passed as first argument to portdb.xmatch - to apply the wanted visibility filters - - @rtype: list of strings - @return: a list with the matching versions - """ - if match_type == "default" or not hasattr(portdb, "xmatch"): - mylist = portdb.match(re.sub("-r[0-9]+$", "", revisionAtom[2:])) - else: - mylist = portdb.xmatch(match_type, re.sub("-r[0-9]+$", "", revisionAtom[2:])) - rValue = [] - for v in mylist: - r1 = portage.pkgsplit(v)[-1][1:] - r2 = portage.pkgsplit(revisionAtom[3:])[-1][1:] - if eval(r1+" "+revisionAtom[0:2]+" "+r2): - rValue.append(v) - return rValue - - -def getMinUpgrade(vulnerableList, unaffectedList, minimize=True): - """ - Checks if the systemstate is matching an atom in - I{vulnerableList} and returns string describing - the lowest version for the package that matches an atom in - I{unaffectedList} and is greater than the currently installed - version or None if the system is not affected. Both - I{vulnerableList} and I{unaffectedList} should have the - same base package. - - @type vulnerableList: List of Strings - @param vulnerableList: atoms matching vulnerable package versions - @type unaffectedList: List of Strings - @param unaffectedList: atoms matching unaffected package versions - @type minimize: Boolean - @param minimize: True for a least-change upgrade, False for emerge-like algorithm - - @rtype: String | None - @return: the lowest unaffected version that is greater than - the installed version. - """ - rValue = None - v_installed = [] - u_installed = [] - for v in vulnerableList: - v_installed += match(v, "vartree") - - for u in unaffectedList: - u_installed += match(u, "vartree") - - install_unaffected = True - for i in v_installed: - if i not in u_installed: - install_unaffected = False - - if install_unaffected: - return rValue - - for u in unaffectedList: - mylist = match(u, "porttree", match_type="match-all") - for c in mylist: - c_pv = portage.catpkgsplit(c) - i_pv = portage.catpkgsplit(portage.best(v_installed)) - if portage.pkgcmp(c_pv[1:], i_pv[1:]) > 0 \ - and (rValue == None \ - or not match("="+rValue, "porttree") \ - or (minimize ^ (portage.pkgcmp(c_pv[1:], portage.catpkgsplit(rValue)[1:]) > 0)) \ - and match("="+c, "porttree")) \ - and portage.db["/"]["porttree"].dbapi.aux_get(c, ["SLOT"]) == portage.db["/"]["vartree"].dbapi.aux_get(portage.best(v_installed), ["SLOT"]): - rValue = c_pv[0]+"/"+c_pv[1]+"-"+c_pv[2] - if c_pv[3] != "r0": # we don't like -r0 for display - rValue += "-"+c_pv[3] - return rValue - - -# simple Exception classes to catch specific errors -class GlsaTypeException(Exception): - def __init__(self, doctype): - Exception.__init__(self, "wrong DOCTYPE: %s" % doctype) - -class GlsaFormatException(Exception): - pass - -class GlsaArgumentException(Exception): - pass - -# GLSA xml data wrapper class -class Glsa: - """ - This class is a wrapper for the XML data and provides methods to access - and display the contained data. - """ - def __init__(self, myid, myconfig): - """ - Simple constructor to set the ID, store the config and gets the - XML data by calling C{self.read()}. - - @type myid: String - @param myid: String describing the id for the GLSA object (standard - GLSAs have an ID of the form YYYYMM-nn) or an existing - filename containing a GLSA. - @type myconfig: portage.config - @param myconfig: the config that should be used for this object. - """ - if re.match(r'\d{6}-\d{2}', myid): - self.type = "id" - elif os.path.exists(myid): - self.type = "file" - else: - raise GlsaArgumentException("Given ID "+myid+" isn't a valid GLSA ID or filename.") - self.nr = myid - self.config = myconfig - self.read() - - def read(self): - """ - Here we build the filename from the config and the ID and pass - it to urllib to fetch it from the filesystem or a remote server. - - @rtype: None - @return: None - """ - if self.config["CHECKMODE"] == "local": - repository = "file://" + self.config["GLSA_DIR"] - else: - repository = self.config["GLSA_SERVER"] - if self.type == "file": - myurl = "file://"+self.nr - else: - myurl = repository + self.config["GLSA_PREFIX"] + str(self.nr) + self.config["GLSA_SUFFIX"] - self.parse(urllib.urlopen(myurl)) - return None - - def parse(self, myfile): - """ - This method parses the XML file and sets up the internal data - structures by calling the different helper functions in this - module. - - @type myfile: String - @param myfile: Filename to grab the XML data from - @rtype: None - @returns: None - """ - self.DOM = xml.dom.minidom.parse(myfile) - if not self.DOM.doctype: - raise GlsaTypeException(None) - elif self.DOM.doctype.systemId != "http://www.gentoo.org/dtd/glsa.dtd": - raise GlsaTypeException(self.DOM.doctype.systemId) - myroot = self.DOM.getElementsByTagName("glsa")[0] - if self.type == "id" and myroot.getAttribute("id") != self.nr: - raise GlsaFormatException("filename and internal id don't match:" + myroot.getAttribute("id") + " != " + self.nr) - - # the simple (single, required, top-level, #PCDATA) tags first - self.title = getText(myroot.getElementsByTagName("title")[0], format="strip") - self.synopsis = getText(myroot.getElementsByTagName("synopsis")[0], format="strip") - self.announced = getText(myroot.getElementsByTagName("announced")[0], format="strip") - self.revised = getText(myroot.getElementsByTagName("revised")[0], format="strip") - - # now the optional and 0-n toplevel, #PCDATA tags and references - try: - self.access = getText(myroot.getElementsByTagName("access")[0], format="strip") - except IndexError: - self.access = "" - self.bugs = getMultiTagsText(myroot, "bug", format="strip") - self.references = getMultiTagsText(myroot.getElementsByTagName("references")[0], "uri", format="keep") - - # and now the formatted text elements - self.description = getText(myroot.getElementsByTagName("description")[0], format="xml") - self.workaround = getText(myroot.getElementsByTagName("workaround")[0], format="xml") - self.resolution = getText(myroot.getElementsByTagName("resolution")[0], format="xml") - self.impact_text = getText(myroot.getElementsByTagName("impact")[0], format="xml") - self.impact_type = myroot.getElementsByTagName("impact")[0].getAttribute("type") - try: - self.background = getText(myroot.getElementsByTagName("background")[0], format="xml") - except IndexError: - self.background = "" - - # finally the interesting tags (product, affected, package) - self.glsatype = myroot.getElementsByTagName("product")[0].getAttribute("type") - self.product = getText(myroot.getElementsByTagName("product")[0], format="strip") - self.affected = myroot.getElementsByTagName("affected")[0] - self.packages = {} - for p in self.affected.getElementsByTagName("package"): - name = p.getAttribute("name") - if not name in self.packages: - self.packages[name] = [] - tmp = {} - tmp["arch"] = p.getAttribute("arch") - tmp["auto"] = (p.getAttribute("auto") == "yes") - tmp["vul_vers"] = [makeVersion(v) for v in p.getElementsByTagName("vulnerable")] - tmp["unaff_vers"] = [makeVersion(v) for v in p.getElementsByTagName("unaffected")] - tmp["vul_atoms"] = [makeAtom(name, v) for v in p.getElementsByTagName("vulnerable")] - tmp["unaff_atoms"] = [makeAtom(name, v) for v in p.getElementsByTagName("unaffected")] - self.packages[name].append(tmp) - # TODO: services aren't really used yet - self.services = self.affected.getElementsByTagName("service") - return None - - def dump(self, outstream=sys.stdout): - """ - Dumps a plaintext representation of this GLSA to I{outfile} or - B{stdout} if it is ommitted. You can specify an alternate - I{encoding} if needed (default is latin1). - - @type outstream: File - @param outfile: Stream that should be used for writing - (defaults to sys.stdout) - """ - width = int(self.config["PRINTWIDTH"]) - outstream.write(center("GLSA %s: \n%s" % (self.nr, self.title), width)+"\n") - outstream.write((width*"=")+"\n") - outstream.write(wrap(self.synopsis, width, caption="Synopsis: ")+"\n") - outstream.write("Announced on: %s\n" % self.announced) - outstream.write("Last revised on: %s\n\n" % self.revised) - if self.glsatype == "ebuild": - for k in self.packages.keys(): - pkg = self.packages[k] - for path in pkg: - vul_vers = "".join(path["vul_vers"]) - unaff_vers = "".join(path["unaff_vers"]) - outstream.write("Affected package: %s\n" % k) - outstream.write("Affected archs: ") - if path["arch"] == "*": - outstream.write("All\n") - else: - outstream.write("%s\n" % path["arch"]) - outstream.write("Vulnerable: %s\n" % vul_vers) - outstream.write("Unaffected: %s\n\n" % unaff_vers) - elif self.glsatype == "infrastructure": - pass - if len(self.bugs) > 0: - outstream.write("\nRelated bugs: ") - for i in range(0, len(self.bugs)): - outstream.write(self.bugs[i]) - if i < len(self.bugs)-1: - outstream.write(", ") - else: - outstream.write("\n") - if self.background: - outstream.write("\n"+wrap(self.background, width, caption="Background: ")) - outstream.write("\n"+wrap(self.description, width, caption="Description: ")) - outstream.write("\n"+wrap(self.impact_text, width, caption="Impact: ")) - outstream.write("\n"+wrap(self.workaround, width, caption="Workaround: ")) - outstream.write("\n"+wrap(self.resolution, width, caption="Resolution: ")) - myreferences = "" - for r in self.references: - myreferences += (r.replace(" ", SPACE_ESCAPE)+NEWLINE_ESCAPE+" ") - outstream.write("\n"+wrap(myreferences, width, caption="References: ")) - outstream.write("\n") - - def isVulnerable(self): - """ - Tests if the system is affected by this GLSA by checking if any - vulnerable package versions are installed. Also checks for affected - architectures. - - @rtype: Boolean - @returns: True if the system is affected, False if not - """ - vList = [] - rValue = False - for k in self.packages.keys(): - pkg = self.packages[k] - for path in pkg: - if path["arch"] == "*" or self.config["ARCH"] in path["arch"].split(): - for v in path["vul_atoms"]: - rValue = rValue \ - or (len(match(v, "vartree")) > 0 \ - and getMinUpgrade(path["vul_atoms"], path["unaff_atoms"])) - return rValue - - def isApplied(self): - """ - Looks if the GLSA IDis in the GLSA checkfile to check if this - GLSA was already applied. - - @rtype: Boolean - @returns: True if the GLSA was applied, False if not - """ - aList = portage.grabfile(self.config["CHECKFILE"]) - return (self.nr in aList) - - def inject(self): - """ - Puts the ID of this GLSA into the GLSA checkfile, so it won't - show up on future checks. Should be called after a GLSA is - applied or on explicit user request. - - @rtype: None - @returns: None - """ - if not self.isApplied(): - checkfile = open(self.config["CHECKFILE"], "a+") - checkfile.write(self.nr+"\n") - checkfile.close() - return None - - def getMergeList(self, least_change=True): - """ - Returns the list of package-versions that have to be merged to - apply this GLSA properly. The versions are as low as possible - while avoiding downgrades (see L{getMinUpgrade}). - - @type least_change: Boolean - @param least_change: True if the smallest possible upgrade should be selected, - False for an emerge-like algorithm - @rtype: List of Strings - @return: list of package-versions that have to be merged - """ - rValue = [] - for pkg in self.packages.keys(): - for path in self.packages[pkg]: - update = getMinUpgrade(path["vul_atoms"], path["unaff_atoms"], minimize=least_change) - if update: - rValue.append(update) - return rValue diff --git a/src/revdep-rebuild/99revdep-rebuild b/src/revdep-rebuild/99revdep-rebuild deleted file mode 100644 index bdaecc7..0000000 --- a/src/revdep-rebuild/99revdep-rebuild +++ /dev/null @@ -1,21 +0,0 @@ -# Default revdep-rebuild configuration file -# -# revdep-rebuild no longer uses hardcoded paths. To change the default -# behavior the following variables can be changed: -# -# LD_LIBRARY_MASK - Mask of specially evaluated libraries -# -# SEARCH_DIRS - List of directories to search for executables and libraries -# Use this for directories that are not included in PATH or ld.so.conf. -# An application should normally not have to set this variable -# -# SEARCH_DIRS_MASK - List of directories to not search -# Use this for directories that should not be searched by revdep-rebuild -# This is normally used by binary packages such as openoffice-bin -# -# Note: This file is sourced using bash by the revdep-rebuild script - -LD_LIBRARY_MASK="libodbcinst.so libodbc.so libjava.so libjvm.so" -SEARCH_DIRS="/bin /sbin /usr/bin /usr/sbin /lib* /usr/lib*" -SEARCH_DIRS_MASK="/lib*/modules" - diff --git a/src/revdep-rebuild/AUTHORS b/src/revdep-rebuild/AUTHORS deleted file mode 100644 index b3d9b32..0000000 --- a/src/revdep-rebuild/AUTHORS +++ /dev/null @@ -1,2 +0,0 @@ -Stanislav Brabec (original author) -Paul Varner <fuzzyray@gentoo.org> diff --git a/src/revdep-rebuild/ChangeLog b/src/revdep-rebuild/ChangeLog deleted file mode 100644 index 9060781..0000000 --- a/src/revdep-rebuild/ChangeLog +++ /dev/null @@ -1,9 +0,0 @@ -2005-06-05 Paul Varner <fuzzyray@gentoo.org> - - * ChangeLog moved to main gentoolkit ChangeLog - -2004-01-07 Karl Trygve Kalleberg <karltk@gentoo.org> - - * Added Makefile - * Copied revdep-rebuild script from app-portage/gentoolkit - diff --git a/src/revdep-rebuild/Makefile b/src/revdep-rebuild/Makefile deleted file mode 100644 index d509681..0000000 --- a/src/revdep-rebuild/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2004 Karl Trygve Kalleberg <karltk@gentoo.org> -# Copyright 2004 Gentoo Technologies, Inc. -# Distributed under the terms of the GNU General Public License v2 -# -# $Header$ - -include ../../makedefs.mak - -all: - echo "AIGBURTH (AYG-berth n.) Any piece of readily identifiable anatomy found among cooked meat." - -dist: - mkdir -p ../../$(distdir)/src/revdep-rebuild - cp Makefile AUTHORS README TODO ChangeLog revdep-rebuild revdep-rebuild.1 99revdep-rebuild ../../$(distdir)/src/revdep-rebuild/ - -install: - - install -m 0755 revdep-rebuild $(bindir)/ - install -d $(docdir)/revdep-rebuild - install -m 0644 AUTHORS README TODO $(docdir)/revdep-rebuild/ - install -m 0644 revdep-rebuild.1 $(mandir)/ - install -d $(sysconfdir)/revdep-rebuild - install -m 0644 99revdep-rebuild $(sysconfdir)/revdep-rebuild/ diff --git a/src/revdep-rebuild/README b/src/revdep-rebuild/README deleted file mode 100644 index 3a51d9f..0000000 --- a/src/revdep-rebuild/README +++ /dev/null @@ -1,4 +0,0 @@ -This tool scans libraries and binaries for broken shared lib dependencies -and fixes them by re-emerging those broken binaries and shared libraries. - -- Alastair Tse <liquidx@gentoo.org> diff --git a/src/revdep-rebuild/TODO b/src/revdep-rebuild/TODO deleted file mode 100644 index d9f6350..0000000 --- a/src/revdep-rebuild/TODO +++ /dev/null @@ -1,7 +0,0 @@ -- revdep cache in /var/cache - - list all .so files this package depends on - - use timestamps of files to know when to rebuild - - if ts of cache is older than any of the package's contained - files, we must rebuild -- update to use equery/gentoolkit -- rewrite in python and/or eclectic module diff --git a/src/revdep-rebuild/find_pkgs.py b/src/revdep-rebuild/find_pkgs.py deleted file mode 100755 index 7013813..0000000 --- a/src/revdep-rebuild/find_pkgs.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/python -# Copyright 1999-2005 Gentoo Foundation -# $Header$ - -# Temporary script to find package versions and slot for revdep-rebuild - -import sys - -sys.path.insert(0, "/usr/lib/gentoolkit/pym") -import gentoolkit - -for pkgname in sys.argv[1:]: - matches = gentoolkit.find_packages(pkgname) - for pkg in matches: - (cat, name, ver, rev) = gentoolkit.split_package_name(pkg.get_cpv()) - slot = pkg.get_env_var("SLOT") - if rev == "r0": - fullversion = ver - else: - fullversion = ver + "-" + rev - - print name + " " + fullversion + " (" + slot + ")" diff --git a/src/revdep-rebuild/revdep-rebuild b/src/revdep-rebuild/revdep-rebuild deleted file mode 100755 index 72efba0..0000000 --- a/src/revdep-rebuild/revdep-rebuild +++ /dev/null @@ -1,1120 +0,0 @@ -#!/bin/bash -# Copyright 1999-2008 Gentoo Foundation - -# revdep-rebuild: Reverse dependency rebuilder. -# Original Author: Stanislav Brabec -# Rewrite Author: Michael A. Smith -# Current Maintainer: Paul Varner <fuzzyray@gentoo.org> - -# TODO: -# - Use more /etc/init.d/functions.sh -# - Try to reduce the number of global vars - -## -# Global Variables: - -# Must-be-blank: -unset GREP_OPTIONS - -# Readonly variables: -declare -r APP_NAME="${0##*/}" # The name of this application -declare -r OIFS="$IFS" # Save the IFS -declare -r ENV_FILE=0_env.rr # Contains environment variables -declare -r FILES_FILE=1_files.rr # Contains a list of files to search -declare -r LDPATH_FILE=2_ldpath.rr # Contains the LDPATH -declare -r BROKEN_FILE=3_broken.rr # Contains the list of broken files -declare -r ERRORS_FILE=3_errors.rr # Contains the ldd error output -declare -r RAW_FILE=4_raw.rr # Contains the raw list of packages -declare -r OWNERS_FILE=4_owners.rr # Contains the file owners -declare -r PKGS_FILE=4_pkgs.rr # Contains the unsorted bare package names -declare -r EBUILDS_FILE=4_ebuilds.rr # Contains the unsorted atoms - # (Appropriately slotted or versioned) -declare -r ORDER_FILE=5_order.rr # Contains the sorted atoms -declare -r STATUS_FILE=6_status.rr # Contains the ldd error output -declare -ra FILES=( - "$ENV_FILE" - "$FILES_FILE" - "$LDPATH_FILE" - "$BROKEN_FILE" - "$ERRORS_FILE" - "$RAW_FILE" - "$OWNERS_FILE" - "$PKGS_FILE" - "$EBUILDS_FILE" - "$ORDER_FILE" - "$STATUS_FILE" -) - -# "Boolean" variables: Considered "true" if it has any value at all -# "True" indicates we should... -declare FULL_LD_PATH # ...search across the COMPLETE_LD_LIBRARY_PATH -declare KEEP_TEMP # ...not delete tempfiles from the current run -declare ORDER_PKGS # ...sort the atoms in deep dependency order -declare PACKAGE_NAMES # ...emerge by slot, not by versionated atom -declare RM_OLD_TEMPFILES # ...remove tempfiles from prior runs -declare SEARCH_BROKEN # ...search for broken libraries and binaries -declare VERBOSE # ...give verbose output - -# Globals that impact portage directly: -declare EMERGE_DEFAULT_OPTS # String of options portage assumes to be set -declare EMERGE_OPTIONS # Array of options to pass to portage -declare PORTAGE_NICENESS # Renice to this value -declare PORTAGE_ROOT # The root path for portage - -# Customizable incremental variables: -# 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 -declare LD_LIBRARY_MASK # Mask of specially evaluated libraries -declare SEARCH_DIRS # List of dirs to search for executables and libraries -declare SEARCH_DIRS_MASK # List of dirs not to search - -# Other globals: -declare OLDPROG # Previous pass through the progress meter -declare EXACT_PKG # Versionated atom to emerge -declare HEAD_TEXT # Feedback string about the search -declare NOCOLOR # Set to "true" not to output term colors -declare OK_TEXT # Feedback about a search which found no errors -declare RC_NOCOLOR # Hack to insure we respect NOCOLOR -declare REBUILD_LIST # Array of atoms to emerge -declare SKIP_LIST # Array of atoms that cannot be emerged (masked?) -declare SONAME # Soname/soname path pattern given on commandline -declare SONAME_SEARCH # Value of SONAME modified to match ldd's output -declare WORKING_TEXT # Feedback about the search -declare WORKING_DIR # Working directory where cache files are kept - -main() { - # preliminary setup - get_opts "$@" - setup_portage - setup_search_paths_and_masks - get_search_env - echo - - # Search for broken binaries - get_files - get_ldpath - main_checks - - # Associate broken binaries with packages to rebuild - if [[ $PACKAGE_NAMES ]]; then - get_packages - clean_packages - assign_packages_to_ebuilds - else - get_exact_ebuilds - fi - - # Rebuild packages owning broken binaries - get_build_order - rebuild - - # All done - cleanup -} -## -# Refuse to delete anything before we cd to our tmpdir -# (See mkdir_and_cd_to_tmpdir() -rm() { - eerror "I was instructed to rm '$@'" - die 1 "Refusing to delete anything before changing to temporary directory." -} -: <<'EW' -## -# GNU find has -executable, but if our users' finds do not have that flag -# we emulate it with this function. Also emulates -writable and -readable. -# 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 find itself should be executable. - local testsubject="$(type -P find)" - if [[ $(command find "$testsubject" -executable 2> /dev/null) ]]; then - unset -f find # We can just use the command find - elif [[ $(command find "$testsubject" -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 "$testsubject" -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 '{}' \; -print}) - a=(${a[@]//-writable/-exec test -w '{}' \; -print}) - a=(${a[@]//-readable/-exec test -r '{}' \; -print}) - command find "${a[@]}" - } - fi - find "$@" -} -EW - -print_usage() { -cat << EOF -Usage: $APP_NAME [OPTIONS] [--] [EMERGE_OPTIONS] - -Broken reverse dependency rebuilder. - - -C, --nocolor Turn off colored output - -d, --debug Print way too much information (uses bash's set -xv) - -e, --exact Emerge based on exact package version - -h, --help Print this usage - -i, --ignore Ignore temporary files from previous runs - -k, --keep-temp Do not delete temporary files on exit - -L, --library NAME Emerge existing packages that use the library with NAME - --library=NAME NAME can be a full path to the library or a basic - regular expression (man grep) - -l, --no-ld-path Do not set LD_LIBRARY_PATH - -o, --no-order Do not check the build order - (Saves time, but may cause breakage.) - -p, --pretend Do a trial run without actually emerging anything - (also passed to emerge command) - -P, --no-progress Turn off the progress meter - -q, --quiet Be less verbose (also passed to emerge command) - -v, --verbose Be more verbose (also passed to emerge command) - -Calls emerge, options after -- are ignored by $APP_NAME -and passed directly to emerge. - -Report bugs to <http://bugs.gentoo.org> -EOF -} -## -# Usage: progress i n -# i: current item -# n: total number of items to process -progress() { - if [[ -t 1 ]]; then - progress() { - local curProg=$(( $1 * 100 / $2 )) - (( curProg == OLDPROG )) && return # no change, output nothing - OLDPROG="$curProg" # must be a global variable - (( $1 == $2 )) && local lb=$'\n' - echo -ne '\r \r'"[ $curProg% ] $lb" - } - progress $@ - else # STDOUT is not a tty. Disable progress meter. - progress() { :; } - fi -} -## -# Usage: countdown n -# n: number of seconds to count -countdown() { - local i - for ((i=1; i<$1; i++)); do - echo -ne '\a.' - ((i<$1)) && sleep 1 - done - echo -e '\a.' -} -## -# Replace whitespace with linebreaks, normalize repeated '/' chars, and sort -u -# (If any libs have whitespace in their filenames, someone needs punishment.) -clean_var() { - gawk 'BEGIN {RS="[[:space:]]"} - /-\*/ {exit} - /[^[:space:]]/ {gsub(/\/\/+/, "/"); print}' | sort -u -} -## -# Exit and optionally output to sterr -die() { - local status=$1 - shift - eerror "$@" - exit $status -} -## -# What to do when dynamic linking is consistent -clean_exit() { - if [[ ! $KEEP_TEMP ]]; then - rm -f "${FILES[@]}" - if [[ "$WORKING_DIR" != "/var/cache/${APP_NAME}" ]]; then - # Remove the working directory - builtin cd; rmdir "$WORKING_DIR" - fi - fi - echo - einfo "$OK_TEXT... All done. " - exit 0 -} -## -# Get the name of the package that owns a file or list of files given as args. -get_file_owner() { - local IFS=$'\n' - # ${*/%/ } adds a space to the end of each object name to prevent false - # matches, for example /usr/bin/dia matching /usr/bin/dialog (bug #196460). - find -L /var/db/pkg -name CONTENTS -print0 | - xargs -0 grep -Fl "${*/%/ }" | - sed 's:/var/db/pkg/\(.*\)/CONTENTS:\1:' -} -## -# Normalize some EMERGE_OPTIONS -normalize_emerge_opts() { - # Normalize some EMERGE_OPTIONS - EMERGE_OPTIONS=(${EMERGE_OPTIONS[@]/%-p/--pretend}) - EMERGE_OPTIONS=(${EMERGE_OPTIONS[@]/%-f/--fetchonly}) - EMERGE_OPTIONS=(${EMERGE_OPTIONS[@]/%-v/--verbose}) -} -## -# Use the color preference from portage -setup_color() { - # This should still work if NOCOLOR is set by the -C flag or in the user's - # environment. - export NOCOLOR=$(portageq envvar NOCOLOR) - [[ $NOCOLOR = yes || $NOCOLOR = true ]] && export RC_NOCOLOR=yes # HACK! (grr) - . /etc/init.d/functions.sh -} -## -# Die if an argument is missing. -die_if_missing_arg() { - [[ ! $2 || $2 = -* ]] && die 1 "Missing expected argument to $1" -} -## -# Die because an option is not recognized. -die_invalid_option() { - # Can't use eerror and einfo because this gets called before function.sh - # is sourced - echo - echo "Encountered unrecognized option $1." >&2 - echo - echo "$APP_NAME no longer automatically passes unrecognized options to portage." - echo "Separate emerge-only options from revdep-rebuild options with the -- flag." - echo - echo "For example, $APP_NAME -v -- --ask" - echo - echo "See the man page or $APP_NAME -h for more detail." - echo - exit 1 -} -## -# Warn about deprecated options. -warn_deprecated_opt() { - # Can't use eerror and einfo because this gets called before function.sh - # is sourced - echo - echo "Encountered deprecated option $1." >&2 - [[ $2 ]] && echo "Please use $2 instead." >&2 -} -## -# Get whole-word commandline options preceded by two dashes. -get_longopts() { - case $1 in - --nocolor) export NOCOLOR="yes";; - --no-color) warn_deprecated_opt "$1" "--nocolor" - export NOCOLOR="yes";; - --debug) set -xv;; - --exact) unset PACKAGE_NAMES;; - --help) print_usage - exit 0;; - --ignore) RM_OLD_TEMPFILES=1;; - --keep-temp) KEEP_TEMP=1;; - --library=*) # TODO: check for invalid values - SONAME="${1#*=}" - unset SEARCH_BROKEN;; - --soname=*|--soname-regexp=*) # TODO: check for invalid values - warn_deprecated_opt "${1%=*}" "--library" - SONAME="${1#*=}" - unset SEARCH_BROKEN;; - --library) # TODO: check for invalid values - die_if_missing_arg $1 $2 - shift - SONAME="$1" - unset SEARCH_BROKEN;; - --soname|--soname-regexp) # TODO: check for invalid values - warn_deprecated_opt "$1" "--library" - die_if_missing_arg $1 $2 - shift - SONAME="$1" - unset SEARCH_BROKEN;; - --no-ld-path) unset FULL_LD_PATH;; - --no-order) unset ORDER_PKGS;; - --no-progress) progress() { :; };; - --pretend) EMERGE_OPTIONS+=("--pretend");; - --quiet) echo_v() { :; } - progress() { :; } - quiet=1 - EMERGE_OPTIONS+=($1);; - --verbose) VERBOSE=1 - EMERGE_OPTIONS+=("--verbose");; - --extra-verbose) warn_deprecated_opt "$1" "--verbose" - VERBOSE=1 - EMERGE_OPTIONS+=("--verbose");; - --package-names) # No longer used, since it is the - # default. We accept it for - # backwards compatibility. - warn_deprecated_opt "$1" - PACKAGE_NAMES=1;; - *) die_invalid_option $1;; - esac -} - -## -# Get single-letter commandline options preceded by a single dash. -get_shortopts() { - local OPT OPTSTRING OPTARG OPTIND - while getopts ":CdehikL:loPpqu:vX" OPT; do - case "$OPT" in - C) # TODO: Match syntax with the rest of gentoolkit - export NOCOLOR="yes";; - d) set -xv;; - e) unset PACKAGE_NAMES;; - h) print_usage - exit 0;; - i) RM_OLD_TEMPFILES=1;; - k) KEEP_TEMP=1;; - L) # TODO: Check for invalid values - SONAME="${OPTARG#*=}" - unset SEARCH_BROKEN;; - l) unset FULL_LD_PATH;; - o) unset ORDER_PKGS;; - P) progress() { :; };; - p) EMERGE_OPTIONS+=("--pretend");; - q) echo_v() { :; } - progress() { :; } - quiet=1 - EMERGE_OPTIONS+=("--quiet");; - v) VERBOSE=1 - EMERGE_OPTIONS+=("--verbose");; - X) # No longer used, since it is the default. - # We accept it for backwards compatibility. - warn_deprecated_opt "-X" - PACKAGE_NAMES=1;; - *) die_invalid_option "-$OPTARG";; - esac - done -} -## -# Get command-line options. -get_opts() { - local avoid_utils - local -a args - echo_v() { ewarn "$@"; } - unset VERBOSE KEEP_TEMP EMERGE_OPTIONS RM_OLD_TEMPFILES - ORDER_PKGS=1 - PACKAGE_NAMES=1 - SONAME="not found" - SEARCH_BROKEN=1 - FULL_LD_PATH=1 - while [[ $1 ]]; do - case $1 in - --) shift - EMERGE_OPTIONS+=("$@") - break;; - -*) while true; do - args+=("$1") - shift - [[ ${1:--} = -* ]] && break - done - if [[ ${args[0]} = --* ]]; then - get_longopts "${args[@]}" - else - get_shortopts "${args[@]}" - fi;; - *) die_invalid_option "$1";; - esac - unset args - done - - setup_color - normalize_emerge_opts - - # If the user is not super, add --pretend to EMERGE_OPTIONS - if [[ ${EMERGE_OPTIONS[@]} != *--pretend* && $UID -ne 0 ]]; then - ewarn "You are not superuser. Adding --pretend to emerge options." - EMERGE_OPTIONS+=(--pretend) - fi -} -## -# Is there a --pretend or --fetchonly flag in the EMERGE_OPTIONS array? -is_real_merge() { - [[ ${EMERGE_OPTIONS[@]} != *--pretend* && - ${EMERGE_OPTIONS[@]} != *--fetchonly* ]] -} -## -# Clean up temporary files and exit -cleanup_and_die() { - rm -f "$@" - die 1 " ...terminated. Removing incomplete $@." -} -## -# Clean trap -clean_trap() { - trap "cleanup_and_die $*" SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM - rm -f "$@" -} -## -# Returns 0 if the first arg is found in the remaining args, 1 otherwise -# (Returns 2 if given fewer than 2 arguments) -has() { - (( $# > 1 )) || return 2 - local IFS=$'\a' target="$1" - shift - [[ $'\a'"$*"$'\a' = *$'\a'$target$'\a'* ]] -} -## -# Dies when it can't change directories -cd() { - if builtin cd -P "$@"; then - if [[ $1 != $PWD ]]; then - # Some symlink malfeasance is going on - die 1 "Working directory expected to be $1, but it is $PWD" - fi - else - die 1 "Unable to change working directory to '$@'" - fi -} -## -# Tries not to delete any files or directories it shouldn't -setup_rm() { - ## - # Anything in the FILES array in tmpdir is fair game for removal - rm() { - local i IFS=$'\a' - [[ $APP_NAME ]] || die 1 '$APP_NAME is not defined! (This is a bug.)' - case $@ in - */*|*-r*|*-R*) die 1 "Oops, I'm not allowed to delete that. ($@)";; - esac - for i; do - # Don't delete files that are not listed in the array - # Allow no slashes or recursive deletes at all. - case $i in - */*|-*r*|-*R*) :;; # Not OK - -*) continue;; # OK - esac - has "$i" "${FILES[@]}" && continue - die 1 "Oops, I'm not allowed to delete that. ($@)" - done - command rm "$@" - } - # delete this setup function so it's harmless to re-run - setup_rm() { :; } -} -## -# Make our temporary files directory -# $1 - directory name -# $2 - user name -verify_tmpdir() { - umask 007 || die $? "Unable to set umask 007" - if [[ ! $1 ]]; then - die 1 'Temporary file path is unset! (This is a bug.)' - elif [[ -d $1 ]]; then - # HACK: I hate using find this way - if [[ $(find "$1" -type d ! \( -user $2 -perm -0700 \) ) ]]; then - eerror "Incorrect permissions on $1" - eerror "or at least one file in $1." - die 1 "Please make sure it's not a symlink and then remove it." - fi - cd "$1" - else - die 1 "Unable to find a satisfactory location for temporary files ($1)" - fi - [[ $VERBOSE ]] && einfo "Temporary cache files are located in $PWD" - setup_rm -} -get_search_env() { - local new_env - local old_env - local uid=$(python -c 'import os; import pwd; print pwd.getpwuid(os.getuid())[0]') - # Find a place to put temporary files - if [[ "$uid" == "root" ]]; then - local tmp_target="/var/cache/${APP_NAME}" - else - local tmp_target="$(mktemp -d -t revdep-rebuild.XXXXXXXXXX)" - fi - - # From here on all work is done inside the temporary directory - verify_tmpdir "$tmp_target" "$uid" - WORKING_DIR="$tmp_target" - - 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 "<space>$SONAME<space>" - SONAME_SEARCH=" $SONAME " - # Escape the "/" characters - SONAME_SEARCH="${SONAME_SEARCH//\//\\/}" - else - # Set to "<tab>$SONAME<space>" - SONAME_SEARCH=$'\t'"$SONAME " - fi - HEAD_TEXT="using $SONAME" - OK_TEXT="There are no dynamic links to $SONAME" - unset WORKING_TEXT - fi - - # If any of our temporary files are older than 1 day, remove them all - if [[ ! $KEEP_TEMP ]]; then - while read; do - RM_OLD_TEMPFILES=1 - break - done < <(find -L . -maxdepth 1 -type f -name '*.rr' -mmin +1440 -print 2>/dev/null) - fi - - # Compare old and new environments - # Don't use our previous files if environment doesn't match - new_env=$( - # We do not care if these emerge options change - EMERGE_OPTIONS=(${EMERGE_OPTIONS[@]//--pretend/}) - EMERGE_OPTIONS=(${EMERGE_OPTIONS[@]//--fetchonly/}) - EMERGE_OPTIONS=(${EMERGE_OPTIONS[@]//--verbose/}) - cat <<- 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[@]}" - ORDER_PKGS="$ORDER_PKGS" - FULL_LD_PATH="$FULL_LD_PATH" - EOF - ) - if [[ -r "$ENV_FILE" && -s "$ENV_FILE" ]]; then - old_env=$(<"$ENV_FILE") - if [[ $old_env != $new_env ]]; then - ewarn 'Environment mismatch from previous run, deleting temporary files...' - RM_OLD_TEMPFILES=1 - fi - else - # No env file found, silently delete any other tempfiles that may exist - RM_OLD_TEMPFILES=1 - fi - - # If we should remove old tempfiles, do so - if [[ $RM_OLD_TEMPFILES ]]; then - rm -f "${FILES[@]}" - else - for file in "${FILES[@]}"; do - if [ -e "$file" ]; then - chown ${uid}:portage "$file" - chmod 700 "$file" - fi - done - fi - - # Save the environment in a file for next time - echo "$new_env" > "$ENV_FILE" - - [[ $VERBOSE ]] && echo $'\n'"$APP_NAME environment:"$'\n'"$new_env" - - echo - einfo "Checking reverse dependencies" - einfo "Packages containing binaries and libraries $HEAD_TEXT" - einfo "will be emerged." -} - -get_files() { - einfo "Collecting system binaries and libraries" - if [[ -r "$FILES_FILE" && -s "$FILES_FILE" ]]; then - einfo "Found existing $FILES_FILE" - else - # Be safe and remove any extraneous temporary files - # Don't remove 0_env.rr - The first file in the array - rm -f "${FILES[@]:1}" - - clean_trap "$FILES_FILE" - - if [[ $SEARCH_DIRS_MASK ]]; then - findMask=($SEARCH_DIRS_MASK) - findMask="${findMask[@]/#/-o -path }" - findMask="( ${findMask#-o } ) -prune -o" - fi - # TODO: Check this -- afaict SEARCH_DIRS isn't an array, so this should just be $SEARCH_DIRS? - find ${SEARCH_DIRS[@]} $findMask -type f \( -perm -u+x -o -perm -g+x -o -perm -o+x -o \ - -name '*.so' -o -name '*.so.*' -o -name '*.la' \) -print 2> /dev/null | - sort -u > "$FILES_FILE" || - die $? "find failed to list binary files (This is a bug.)" - einfo "Generated new $FILES_FILE" - fi -} -get_ldpath() { - local COMPLETE_LD_LIBRARY_PATH - [[ $SEARCH_BROKEN && $FULL_LD_PATH ]] || return - einfo 'Collecting complete LD_LIBRARY_PATH' - if [[ -r "$LDPATH_FILE" && -s "$LDPATH_FILE" ]]; then - einfo "Found existing $LDPATH_FILE." - else - clean_trap "$LDPATH_FILE" - # 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:/[^/]*$::' < "$FILES_FILE" | sort -ru) - ) - IFS=':' - COMPLETE_LD_LIBRARY_PATH="${COMPLETE_LD_LIBRARY_PATH[*]}" - IFS="$OIFS" - echo "$COMPLETE_LD_LIBRARY_PATH" > "$LDPATH_FILE" - einfo "Generated new $LDPATH_FILE" - fi -} -main_checks() { - local target_file - local -a files - local i=0 - local ldd_output - local ldd_status - local numFiles - local COMPLETE_LD_LIBRARY_PATH - if [[ $SEARCH_BROKEN && $FULL_LD_PATH ]]; then - [[ -r "$LDPATH_FILE" && -s "$LDPATH_FILE" ]] || - die 1 "Unable to find $LDPATH_FILE" - COMPLETE_LD_LIBRARY_PATH=$(<"$LDPATH_FILE") - fi - einfo "Checking dynamic linking $WORKING_TEXT" - if [[ -r "$BROKEN_FILE" && -s "$BROKEN_FILE" ]]; then - einfo "Found existing $BROKEN_FILE." - else - clean_trap "$BROKEN_FILE" "$ERRORS_FILE" - files=($(<"$FILES_FILE")) - numFiles="${#files[@]}" - for target_file in "${files[@]}"; do - if [[ $target_file != *.la ]]; then - # Note: double checking seems to be faster than single with complete path - # (special add ons are rare). - ldd_output=$(ldd "$target_file" 2>> "$ERRORS_FILE" | sort -u) - ldd_status=$? # TODO: Check this for problems with sort - # HACK: if LD_LIBRARY_MASK is null or undefined grep -vF doesn't work - if grep -vF "${LD_LIBRARY_MASK:=$'\a'}" <<< "$ldd_output" | - grep -q "$SONAME_SEARCH"; then - if [[ $SEARCH_BROKEN && $FULL_LD_PATH ]]; then - if LD_LIBRARY_PATH="$COMPLETE_LD_LIBRARY_PATH" ldd "$target_file" 2>/dev/null | - grep -vF "$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 "$target_file" | grep NEEDED | sed "$expr" | sort -u - ) - MISSING_LIBS=$(grep -F "$REQUIRED_LIBS" <<< "$MISSING_LIBS") - if [[ $MISSING_LIBS ]]; then - echo "obj $target_file" >> "$BROKEN_FILE" - echo_v " broken $target_file (requires $MISSING_LIBS)" - fi - fi - else - # FIXME: I hate duplicating code - # Only rebuild for direct dependencies - MISSING_LIBS=$( - expr="/$SONAME_SEARCH/s/^[[:space:]]*\([^[:space:]]*\).*$/\1/p" - sort -u <<< "$ldd_output" | sed -n "$expr" - ) - REQUIRED_LIBS=$( - expr='s/^[[:space:]]*NEEDED[[:space:]]*\([^[:space:]]*\).*/\1/p'; - objdump -x "$target_file" | grep NEEDED | sed "$expr" | sort -u - ) - MISSING_LIBS=$(grep -F "$REQUIRED_LIBS" <<< "$MISSING_LIBS") - if [[ $MISSING_LIBS ]]; then - echo "obj $target_file" >> "$BROKEN_FILE" - if [[ $SEARCH_BROKEN ]]; then - echo_v " broken $target_file (requires $MISSING_LIBS)" - else - echo_v " found $target_file" - fi - fi - fi - fi - elif [[ $SEARCH_BROKEN ]]; then - # Look for broken .la files - la_SEARCH_DIRS="$SEARCH_DIRS" - la_search_dir="" - la_broken="" - la_lib="" - for depend in $( - gawk -F"[=']" '/^dependency_libs/{ - print $3 - }' "$target_file" - ); do - if [[ $depend = /* && ! -e $depend ]]; then - echo "obj $target_file" >> "$BROKEN_FILE" - echo_v " broken $target_file (requires $depend)" - elif [[ $depend = -[LR]/* ]]; then - if ! [[ $'\n'${la_SEARCH_DIRS}$'\n' == *$'\n'${depend#-?}$'\n'* ]]; then - la_SEARCH_DIRS+=$'\n'"${depend#-?}" - fi - elif [[ $depend = "-l"* ]]; then - la_lib="lib${depend#-l}" - la_broken="yes" - IFS=$'\n' - for la_search_dir in $la_SEARCH_DIRS; do - if [[ -e ${la_search_dir}/${la_lib}.so || -e ${la_search_dir}/${la_lib}.a ]]; then - la_broken="no" - fi - done - IFS="$OIFS" - if [[ $la_broken = yes ]]; then - echo "obj $target_file" >> "$BROKEN_FILE" - echo_v " broken $target_file (requires $depend)" - fi - fi - done - unset la_SEARCH_DIRS la_search_dir la_broken la_lib - fi - [[ $VERBOSE ]] && - progress $((++i)) $numFiles $target_file || - progress $((++i)) $numFiles - done - if [[ $SEARCH_BROKEN ]]; then - # Look for missing version - while read target_file; do - echo "obj $target_file" >> "$BROKEN_FILE" - echo_v " broken $target_file (no version information available)" - done < <( - # Regexify LD_LIBRARY_MASK. Exclude it from the search. - LD_LIBRARY_MASK="${LD_LIBRARY_MASK//$'\n'/|}" - gawk -v ldmask="(${LD_LIBRARY_MASK//./\\\.})" ' - /no version information available/ && $0 !~ ldmask { - gsub(/[()]/, "", $NF) - if (seen[$NF]++) next - print $NF - }' "$ERRORS_FILE" - ) - fi - [[ -r "$BROKEN_FILE" && -s "$BROKEN_FILE" ]] || clean_exit - sort -u "$BROKEN_FILE" -o "$BROKEN_FILE" - einfo "Generated new $BROKEN_FILE" - fi -} -get_packages() { - local target_file - local EXACT_PKG - local PKG - local obj - einfo 'Assigning files to packages' - if [[ -r "$RAW_FILE" && -s "$RAW_FILE" ]]; then - einfo "Found existing $RAW_FILE" - else - clean_trap "$RAW_FILE" "$OWNERS_FILE" - while read obj target_file; do - EXACT_PKG=$(get_file_owner $target_file) - if [[ $EXACT_PKG ]]; then - # Strip version information - PKG="${EXACT_PKG%%-r[[:digit:]]*}" - PKG="${PKG%-*}" - echo "$EXACT_PKG" >> "$RAW_FILE" - echo "$target_file -> $EXACT_PKG" >> "$OWNERS_FILE" - echo_v " $target_file -> $PKG" - else - ewarn " !!! $target_file not owned by any package is broken !!!" - echo "$target_file -> (none)" >> "$OWNERS_FILE" - echo_v " $target_file -> (none)" - fi - done < "$BROKEN_FILE" - einfo "Generated new $RAW_FILE and $OWNERS_FILE" - fi - # if we find '(none)' on every line, exit out - if ! grep -qvF '(none)' "$OWNERS_FILE"; then - ewarn "Found some broken files, but none of them were associated with known packages" - ewarn "Unable to proceed with automatic repairs." - ewarn "The broken files are listed in $OWNERS_FILE" - if [[ $VERBOSE ]]; then - ewarn "The broken files are:" - while read filename junk; do - ewarn " $filename" - done < "$OWNERS_FILE" - fi - exit 0 # FIXME: Should we exit 1 here? - fi -} -clean_packages() { - einfo 'Cleaning list of packages to rebuild' - if [[ -r "$PKGS_FILE" && -s "$PKGS_FILE" ]]; then - einfo "Found existing $PKGS_FILE" - else - sort -u "$RAW_FILE" > "$PKGS_FILE" - einfo "Generated new $PKGS_FILE" - fi -} -assign_packages_to_ebuilds() { - local EXACT_PKG - local PKG - local SLOT - einfo 'Assigning packages to ebuilds' - if [[ -r "$EBUILDS_FILE" && -s "$EBUILDS_FILE" ]]; then - einfo "Found existing $EBUILDS_FILE" - elif [[ -r "$PKGS_FILE" && -s "$PKGS_FILE" ]]; then - clean_trap "$EBUILDS_FILE" - while read EXACT_PKG; do - # Get the slot - PKG="${EXACT_PKG%%-r[[:digit:]]*}" - PKG="${PKG%-*}" - SLOT=$(</var/db/pkg/$EXACT_PKG/SLOT) - echo "$PKG:$SLOT" - done < "$PKGS_FILE" > "$EBUILDS_FILE" - einfo "Generated new $EBUILDS_FILE" - else - einfo 'Nothing to rebuild.' - die 1 '(The program should have already quit, so this is a minor bug.)' - fi -} -get_exact_ebuilds() { - einfo 'Assigning files to ebuilds' - if [[ -r $EBUILDS_FILE && -s $EBUILDS_FILE ]]; then - einfo "Found existing $EBUILDS_FILE" - elif [[ -r $BROKEN_FILE && -s $BROKEN_FILE ]]; then - rebuildList=" $(<"$BROKEN_FILE") " - rebuildList=(${rebuildList//[[:space:]]obj[[:space:]]/ }) - get_file_owner "${rebuildList[@]}" | sed 's/^/=/' > "$EBUILDS_FILE" - einfo "Generated new $EBUILDS_FILE" - else - einfo 'Nothing to rebuild.' - die 1 '(The program should have already quit, so this is a minor bug.)' - fi -} -list_skipped_packages() { - ewarn - ewarn 'Portage could not find any version of the following packages it could build:' - ewarn "${SKIP_LIST[@]}" - ewarn - ewarn '(Perhaps they are masked, blocked, or removed from portage.)' - ewarn 'Try to emerge them manually.' - ewarn -} -get_build_order() { - local -r OLD_EMERGE_DEFAULT_OPTS="$EMERGE_DEFAULT_OPTS" - local RAW_REBUILD_LIST - local REBUILD_GREP - local i - if [[ ! $ORDER_PKGS ]]; then - einfo 'Skipping package ordering' - return - fi - einfo 'Evaluating package order' - if [[ -r "$ORDER_FILE" && -s "$ORDER_FILE" ]]; then - einfo "Found existing $ORDER_FILE" - else - clean_trap "$ORDER_FILE" - RAW_REBUILD_LIST=$(<"$EBUILDS_FILE") - if [[ $RAW_REBUILD_LIST ]]; then - export EMERGE_DEFAULT_OPTS="--nospinner --pretend --oneshot --quiet" - RAW_REBUILD_LIST=($RAW_REBUILD_LIST) # convert into array - # If PACKAGE_NAMES is defined we're using slots, not versions - if [[ $PACKAGE_NAMES ]]; then - # Eliminate atoms that can't be built - for i in "${!RAW_REBUILD_LIST[@]}"; do - if [[ "${RAW_REBUILD_LIST[i]}" = *[A-Za-z]* ]]; then - portageq best_visible "$PORTAGE_ROOT" "${RAW_REBUILD_LIST[i]}" >/dev/null && continue - SKIP_LIST+=("${RAW_REBUILD_LIST[i]}") - fi - unset RAW_REBUILD_LIST[i] - done - # If RAW_REBUILD_LIST is empty, then we have nothing to build. - if (( ${#RAW_REBUILD_LIST[@]} == 0 )); then - if (( ${#SKIP_LIST[@]} == 0 )); then - ewarn "The list of packages to skip is empty, but there are no" - ewarn "packages listed to rebuild either. (This is a bug.)" - else - list_skipped_packages - fi - die 1 'Warning: Portage cannot rebuild any of the necessary packages.' - fi - fi - RAW_REBUILD_LIST="${RAW_REBUILD_LIST[@]}" - REBUILD_GREP=$(emerge --nodeps $RAW_REBUILD_LIST | sed 's/\[[^]]*\]//g') - if (( ${PIPESTATUS[0]} == 0 )); then - emerge --deep $RAW_REBUILD_LIST | - sed 's/\[[^]]*\]//g' | - grep -F "$REBUILD_GREP" > "$ORDER_FILE" - fi - - # Here we use the PIPESTATUS from the second emerge, the --deep one. - if (( ${PIPESTATUS[0]} != 0 )); then - eerror - eerror 'Warning: Failed to resolve package order.' - eerror 'Will merge in arbitrary order' - eerror - 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 - countdown 5 - rm -f "$ORDER_FILE" - fi - export EMERGE_DEFAULT_OPTS="$OLD_EMERGE_DEFAULT_OPTS" - else - einfo 'Nothing to rebuild.' - die 1 '(The program should have already quit, so this is a minor bug.)' - fi - fi - [[ -r "$ORDER_FILE" && -s "$ORDER_FILE" ]] && einfo "Generated new $ORDER_FILE" -} - -show_unowned_files() { - if grep -qF '(none)' "$OWNERS_FILE"; then - ewarn "Found some broken files that weren't associated with known packages" - ewarn "The broken files are:" - while read filename junk; do - [[ $junk = *none* ]] && ewarn " $filename" - done < "$OWNERS_FILE" | gawk '!s[$0]++' # (omit dupes) - fi -} -## -# Setup portage and the search paths -setup_portage() { - local PORTAGE_NICENESS=$(portageq envvar PORTAGE_NICENESS) - PORTAGE_ROOT=$(portageq envvar ROOT) - - # Obey 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="${PORTAGE_ROOT:-/}" -} - -## -# Setup the paths to search (and filter the ones to avoid) -setup_search_paths_and_masks() { - local configfile sdir mdir skip_me filter_SEARCH_DIRS - - einfo "Configuring search environment for $APP_NAME" - - # 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 configfile in /etc/revdep-rebuild/*; do - SEARCH_DIRS+=" "$(. $configfile; echo $SEARCH_DIRS) - SEARCH_DIRS_MASK+=" "$(. $configfile; echo $SEARCH_DIRS_MASK) - LD_LIBRARY_MASK+=" "$(. $configfile; 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" && -s "/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 && -s /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") - # Filter masked paths from SEARCH_DIRS - for sdir in ${SEARCH_DIRS} ; do - skip_me= - for mdir in ${SEARCH_DIRS_MASK}; do - [[ ${sdir} == ${mdir}/* ]] && skip_me=1 && break - done - [[ -n ${skip_me} ]] || filter_SEARCH_DIRS+=" ${sdir}" - done - SEARCH_DIRS=$(clean_var <<< "${filter_SEARCH_DIRS}") - [[ $SEARCH_DIRS ]] || die 1 "No search defined -- this is a bug." -} -## -# Rebuild packages owning broken binaries -rebuild() { - if [[ -r $LIST.5_order && -s $LIST.5_order ]]; then - REBUILD_LIST=( $(<"$LIST.5_order") ) - REBUILD_LIST="${REBUILD_LIST[@]/#/=}" - else - REBUILD_LIST=$(sort -u "$EBUILDS_FILE") - fi - - trap - SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM - - einfo 'All prepared. Starting rebuild' - echo "emerge --oneshot ${EMERGE_OPTIONS[@]} $REBUILD_LIST" - - is_real_merge && countdown 10 - - # Link file descriptor #6 with stdin so --ask will work - exec 6<&0 - - # Run in background to correctly handle Ctrl-C - { - EMERGE_DEFAULT_OPTS="--oneshot ${EMERGE_OPTIONS[@]}" emerge $REBUILD_LIST <&6 - echo $? > "$STATUS_FILE" - } & - 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<&- -} -## -# Finish up -cleanup() { - if (( $(<"$STATUS_FILE") != 0 )); then - ewarn - ewarn "$APP_NAME failed to emerge all packages." - ewarn 'you have the following choices:' - einfo "- If emerge failed during the build, fix the problems and re-run $APP_NAME." - einfo '- Use /etc/portage/package.keywords to unmask a newer version of the package.' - einfo " (and remove $ORDER_FILE to be evaluated again)" - einfo '- Modify the above emerge command and run it manually.' - einfo '- Compile or unmerge unsatisfied packages manually,' - einfo ' remove temporary files, and try again.' - einfo ' (you can edit package/ebuild list first)' - einfo - einfo 'To remove temporary files, please run:' - einfo "rm ${WORKING_DIR}/*.rr" - show_unowned_files - exit $EMERGE_STATUS - elif is_real_merge; then - trap_cmd() { - eerror "terminated. Please remove the temporary files manually:" - eerror "rm ${WORKING_DIR}/*.rr" - exit 1 - } - [[ "${SKIP_LIST[@]}" != "" ]] && list_skipped_packages - trap trap_cmd SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM - einfo 'Build finished correctly. Removing temporary files...' - einfo - einfo 'You can re-run revdep-rebuild to verify that all libraries and binaries' - einfo 'are fixed. Possible reasons for remaining inconsistencies include:' - einfo ' orphaned files' - einfo ' deep dependencies' - einfo " packages installed outside of portage's control" - einfo ' specially-evaluated libraries' - if [[ -r "$OWNERS_FILE" && -s "$OWNERS_FILE" ]]; then - show_unowned_files - fi - [[ $KEEP_TEMP ]] || rm "${FILES[@]}" - else - einfo 'Now you can remove -p (or --pretend) from arguments and re-run revdep-rebuild.' - fi -} - -main "$@" diff --git a/src/revdep-rebuild/revdep-rebuild-old b/src/revdep-rebuild/revdep-rebuild-old deleted file mode 100755 index 52d6d19..0000000 --- a/src/revdep-rebuild/revdep-rebuild-old +++ /dev/null @@ -1,720 +0,0 @@ -#!/bin/bash -# Copyright 1999-2007 Gentoo Foundation -# $Header$ - -# revdep-rebuild: Reverse dependency rebuilder. -# Original Author: Stanislav Brabec -# Current Maintainer: Paul Varner <fuzzyray@gentoo.org> - -# 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 - -if [ "$1" = "-h" -o "$1" = "--help" ] -then - echo "Usage: $0 [OPTIONS] [--] [EMERGE_OPTIONS]" - echo - echo "Broken reverse dependency rebuilder." - echo - echo " -X, --package-names Emerge based on package names, not exact versions" - echo " --library NAME Emerge existing packages that use the library with NAME" - echo " --library=NAME NAME can be a full path to the library or a basic" - echo " regular expression (man grep)" - echo " -np, --no-ld-path Do not set LD_LIBRARY_PATH" - echo " -nc, --nocolor Turn off colored output" - echo " -i, --ignore Ignore temporary files from previous runs" - echo " -q, --quiet Be less verbose (also passed to emerge command)" - echo " -vv, --extra-verbose Be extra verbose" - echo - echo "Calls emerge, all other options are used for it (e. g. -p, --pretend)." - echo - echo "Report bugs to <http://bugs.gentoo.org>" - exit 0 -fi - -echo "Configuring search environment for revdep-rebuild" - -# Obey PORTAGE_NICENESS -PORTAGE_NICENESS=$(portageq envvar PORTAGE_NICENESS) -if [ ! -z "$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) -[ -z "$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 -PRELIMINARY_SEARCH_DIRS="$SEARCH_DIRS $(unset SEARCH_DIRS; portageq envvar SEARCH_DIRS)" -PRELIMINARY_SEARCH_DIRS_MASK="$SEARCH_DIRS_MASK $(unset SEARCH_DIRS_MASK; portageq envvar SEARCH_DIRS_MASK)" -PRELIMINARY_LD_LIBRARY_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 $(ls /etc/revdep-rebuild) - do - PRELIMINARY_SEARCH_DIRS="$PRELIMINARY_SEARCH_DIRS $(. /etc/revdep-rebuild/${file}; echo $SEARCH_DIRS)" - PRELIMINARY_SEARCH_DIRS_MASK="$PRELIMINARY_SEARCH_DIRS_MASK $(. /etc/revdep-rebuild/${file}; echo $SEARCH_DIRS_MASK)" - PRELIMINARY_LD_LIBRARY_MASK="$PRELIMINARY_LD_LIBRARY_MASK $(. /etc/revdep-rebuild/${file}; echo $LD_LIBRARY_MASK)" - done -else - PRELIMINARY_SEARCH_DIRS="$PRELIMINARY_SEARCH_DIRS /bin /sbin /usr/bin /usr/sbin /lib* /usr/lib*" - PRELIMINARY_SEARCH_DIRS_MASK="$PRELIMINARY_SEARCH_DIRS_MASK /opt/OpenOffice /usr/lib/openoffice" - PRELIMINARY_LD_LIBRARY_MASK="$PRELIMINARY_LD_LIBRARY_MASK libodbcinst.so libodbc.so libjava.so libjvm.so" -fi - -# Get the ROOTPATH and PATH from /etc/profile.env -if [ -e "/etc/profile.env" ] -then - PRELIMINARY_SEARCH_DIRS="$PRELIMINARY_SEARCH_DIRS $((. /etc/profile.env; echo ${ROOTPATH}:${PATH}) | tr ':' ' ')" -fi - -# Get the directories from /etc/ld.so.conf -if [ -e /etc/ld.so.conf ] -then - PRELIMINARY_SEARCH_DIRS="$PRELIMINARY_SEARCH_DIRS $(grep -v "^#" /etc/ld.so.conf | tr '\n' ' ')" -fi - -# Set the final variables -# Note: Using $(echo $variable) removes extraneous spaces from variable assignment -unset SEARCH_DIRS -for i in $(echo $PRELIMINARY_SEARCH_DIRS) -do - [ "$i" = "-*" ] && break - # Append a / at the end so that links and directories are treated the same by find - # Remove any existing trailing slashes to prevent double-slashes - SEARCH_DIRS="$(echo $SEARCH_DIRS ${i/%\//}/)" -done -# Remove any double-slashes from the path -SEARCH_DIRS="$(echo $SEARCH_DIRS | sed 's:/\+:/:g')" - -unset SEARCH_DIRS_MASK -for i in $(echo $PRELIMINARY_SEARCH_DIRS_MASK) -do - [ "$i" = "-*" ] && break - SEARCH_DIRS_MASK="$(echo $SEARCH_DIRS_MASK $i)" -done - -unset LD_LIBRARY_MASK -for i in $(echo $PRELIMINARY_LD_LIBRARY_MASK) -do - [ "$i" = "-*" ] && break - LD_LIBRARY_MASK="$(echo $LD_LIBRARY_MASK $i)" -done - -# Use the color preference from portage -NOCOLOR=$(portageq envvar NOCOLOR) - -# Base of temporary files names. -touch ${HOME}/.revdep-rebuild_0.test 2>/dev/null -if [ $? -eq 0 ] -then - LIST="${HOME}/.revdep-rebuild" - rm ~/.revdep-rebuild_0.test -else - # Try to use /var/tmp since $HOME is not available - touch /var/tmp/.revdep-rebuild_0.test 2>/dev/null - if [ $? -eq 0 ] - then - LIST="/var/tmp/.revdep-rebuild" - rm /var/tmp/.revdep-rebuild_0.test - else - echo - echo "!!! Unable to write temporary files to either $HOME or /var/tmp !!!" - echo - exit 1 - fi -fi - -shopt -s nullglob -shopt -s expand_aliases -unalias -a - -# Color Definitions -NO="\x1b[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" - -# Check if portage-utils are installed -portageq has_version $PORTAGE_ROOT portage-utils -if [ "$?" -eq 0 ] -then - PORTAGE_UTILS=true -else - PORTAGE_UTILS=false -fi - -alias echo_v=echo - -PACKAGE_NAMES=false -SONAME="not found" -SONAME_GREP=grep -SEARCH_BROKEN=true -EXTRA_VERBOSE=false -KEEP_TEMP=false -FULL_LD_PATH=true - -EMERGE_OPTIONS="" -PRELIMINARY_CALLED_OPTIONS="" -while [ ! -z "$1" ] ; do - case "$1" in - -X | --package-names ) - PACKAGE_NAMES=true - PRELIMINARY_CALLED_OPTIONS="${PRELIMINARY_CALLED_OPTIONS} --package_names" - shift - ;; - -q | --quiet ) - alias echo_v=: - EMERGE_OPTIONS="${EMERGE_OPTIONS} $1" - shift - ;; - --library=* | --soname=* | --soname-regexp=* ) - SONAME="${1#*=}" - SEARCH_BROKEN=false - PRELIMINARY_CALLED_OPTIONS="${PRELIMINARY_CALLED_OPTIONS} --library=${SONAME}" - shift - ;; - --library | --soname | --soname-regexp ) - SONAME="$2" - SEARCH_BROKEN=false - PRELIMINARY_CALLED_OPTIONS="${PRELIMINARY_CALLED_OPTIONS} --library=${SONAME}" - shift 2 - ;; - -nc | --no-color | --nocolor ) - NOCOLOR=true - shift - ;; - -np | --no-ld-path ) - FULL_LD_PATH=false - PRELIMINARY_CALLED_OPTIONS="${PRELIMINARY_CALLED_OPTIONS} --no-ld-path" - shift - ;; - -i | --ignore ) - rm -f ${LIST}* - shift - ;; - --keep-temp ) - KEEPTEMP=true - shift - ;; - -vv | --extra-verbose ) - EXTRA_VERBOSE=true - shift - ;; - -- ) - shift - ;; - * ) - EMERGE_OPTIONS="${EMERGE_OPTIONS} $1" - shift - ;; - esac -done - -EMERGE_OPTIONS=$(echo $EMERGE_OPTIONS | sed 's/^ //') - -if [ -z "$PRELIMINARY_CALLED_OPTIONS" ] -then - CALLED_OPTIONS="" -else - for i in $(echo $PRELIMINARY_CALLED_OPTIONS | tr ' ' '\n'| sort) - do - CALLED_OPTIONS="$(echo $CALLED_OPTIONS $i)" - done -fi - -if [ "$NOCOLOR" = "yes" -o "$NOCOLOR" = "true" ] -then - NOCOLOR=true -else - NOCOLOR=false -fi - -# Make the NOCOLOR variable visible to emerge -export NOCOLOR - -if $NOCOLOR -then - NO="" - BR="" - CY="" - GR="" - RD="" - YL="" - BL="" -fi - -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 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:0:1} == '/' ] ; then - # Set to "<space>$SONAME<space>" - SONAME_SEARCH=" $SONAME " - else - # Set to "<tab>$SONAME<space>" - SONAME_SEARCH=" $SONAME " - fi - LLIST=${LIST}_$(echo "$SONAME_SEARCH$SONAME" | md5sum | head -c 8) - HEAD_TEXT="using $SONAME" - OK_TEXT="There are no dynamic links to $SONAME" - WORKING_TEXT="" -fi - -# If any of our temporary files are older than 1 day, remove them all -[ "$(find "${LIST%/*}/." ! -name . -prune -name "${LIST##*/}*" -type f -mmin +1440)" != "" ] && rm -f ${LIST}* - -# Don't use our previous files if environment doesn't match -if [ -f $LIST.0_env ] -then - PREVIOUS_SEARCH_DIRS=$(. ${LIST}.0_env; echo "$SEARCH_DIRS") - PREVIOUS_SEARCH_DIRS_MASK=$(. ${LIST}.0_env; echo "$SEARCH_DIRS_MASK") - PREVIOUS_LD_LIBRARY_MASK=$(. ${LIST}.0_env; echo "$LD_LIBRARY_MASK") - PREVIOUS_PORTAGE_ROOT=$(. ${LIST}.0_env; echo "$PORTAGE_ROOT") - PREVIOUS_OPTIONS=$(. ${LIST}.0_env; echo "$CALLED_OPTIONS") - if [ "$PREVIOUS_SEARCH_DIRS" != "$SEARCH_DIRS" ] || \ - [ "$PREVIOUS_SEARCH_DIRS_MASK" != "$SEARCH_DIRS_MASK" ] || \ - [ "$PREVIOUS_LD_LIBRARY_MASK" != "$LD_LIBRARY_MASK" ] || \ - [ "$PREVIOUS_PORTAGE_ROOT" != "$PORTAGE_ROOT" ] || \ - [ "$PREVIOUS_OPTIONS" != "$CALLED_OPTIONS" ] - then - echo - echo "Environment mismatch from previous run, deleting temporary files..." - rm -f ${LIST}* - fi -fi - -# Clean up no longer needed environment variables -unset PREVIOUS_SEARCH_DIRS PREVIOUS_SEARCH_DIRS_MASK PREVIOUS_LD_LIBRARY_MASK PREVIOUS_PORTAGE_ROOT PREVIOUS_OPTIONS -unset PRELIMINARY_SEARCH_DIRS PRELIMINARY_SEARCH_DIRS_MASK PRELIMINARY_LD_LIBRARY_MASK PRELIMINARY_CALLED_OPTIONS - -# Log our environment -echo "SEARCH_DIRS=\"$SEARCH_DIRS\"" > $LIST.0_env -echo "SEARCH_DIRS_MASK=\"$SEARCH_DIRS_MASK\"" >> $LIST.0_env -echo "LD_LIBRARY_MASK=\"$LD_LIBRARY_MASK\"" >> $LIST.0_env -echo "PORTAGE_ROOT=\"$PORTAGE_ROOT\"" >> $LIST.0_env -echo "CALLED_OPTIONS=\"$CALLED_OPTIONS\"" >> $LIST.0_env -echo "EMERGE_OPTIONS=\"$EMERGE_OPTIONS\"" >> $LIST.0_env - -if $EXTRA_VERBOSE -then - echo - echo "revdep-rebuild environment:" - cat $LIST.0_env -fi - -echo -echo "Checking reverse dependencies..." -echo -echo "Packages containing binaries and libraries $HEAD_TEXT" -echo "will be emerged." - -echo -echo -n -e "${GR}Collecting system binaries and libraries...${NO}" - -if [ -f $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_*" - - # Hack for the different versions of find. - # Be extra paranoid and pipe results through sed to remove multiple slashes - find_results=$(find /usr/bin/revdep-rebuild -type f -perm /u+x 2>/dev/null) - if [ -z $find_results ] - then - find_results=$(find /usr/bin/revdep-rebuild -type f -perm +u+x 2>/dev/null) - if [ -z $find_results ] - then - echo -e "\n" - echo -e "${RD}Unable to determine how to use find to locate executable files${NO}" - echo -e "${RD}Open a bug at http://bugs.gentoo.org${NO}" - echo - exit 1 - else - # using -perm +u+x for find command - find $SEARCH_DIRS -type f \( -perm +u+x -o -name '*.so' -o -name '*.so.*' -o -name '*.la' \) 2>/dev/null | sort | uniq | sed 's:/\+:/:g' >$LIST.0_files - fi - else - # using -perm /u+x for find command - find $SEARCH_DIRS -type f \( -perm /u+x -o -name '*.so' -o -name '*.so.*' -o -name '*.la' \) 2>/dev/null | sort | uniq | sed 's:/\+:/:g' >$LIST.0_files - fi - - # Remove files that match SEARCH_DIR_MASK - for dir in $SEARCH_DIRS_MASK - do - grep -v "^$dir" $LIST.0_files > $LIST.1_files - mv $LIST.1_files $LIST.0_files - done - - mv $LIST.0_files $LIST.1_files - echo -e " done.\n ($LIST.1_files)" -fi - -if $SEARCH_BROKEN && $FULL_LD_PATH ; 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" - # Ensure that the "trusted" lib directories are at the start of the path - ( - echo /lib* /usr/lib* | sed 's/ /:/g' - sed '/^#/d;s/#.*$//' </etc/ld.so.conf - sed 's:/[^/]*$::' <$LIST.1_files | sort -ru - ) | tr '\n' : | tr -d '\r' | sed 's/:$//' >$LIST.2_ldpath - echo -e " done.\n ($LIST.2_ldpath)" - fi - 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 - echo -n >$LLIST.3_ldd_errors - cat $LIST.1_files | egrep -v '*\.la$' | 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>>$LLIST.3_ldd_errors | grep -v "$LD_MASK" | $SONAME_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_MASK" | $SONAME_GREP -q "$SONAME_SEARCH" ; then - # FIX: I hate duplicating code - # Only build missing direct dependencies - ALL_MISSING_LIBS=$(ldd "$FILE" 2>/dev/null | sort -u | sed -n 's/ \(.*\) => not found/\1/p' | tr '\n' ' ' | sed 's/ $//' ) - REQUIRED_LIBS=$(objdump -x $FILE | grep NEEDED | awk '{print $2}' | tr '\n' ' ' | sed 's/ $//') - MISSING_LIBS="" - for lib in $ALL_MISSING_LIBS - do - if echo $REQUIRED_LIBS | grep -q $lib - then - MISSING_LIBS="$MISSING_LIBS $lib" - fi - done - if [ "$MISSING_LIBS" != "" ] - then - echo "obj $FILE" >>$LLIST.3_rebuild - echo_v " broken $FILE (requires ${MISSING_LIBS})" - fi - fi - else - # FIX: I hate duplicating code - # Only rebuild for direct dependencies - ALL_MISSING_LIBS=$(ldd "$FILE" 2>/dev/null | sort -u | $SONAME_GREP "$SONAME_SEARCH" | awk '{print $1}' | tr '\n' ' ' | sed 's/ $//' ) - REQUIRED_LIBS=$(objdump -x $FILE | grep NEEDED | awk '{print $2}' | tr '\n' ' ' | sed 's/ $//') - MISSING_LIBS="" - for lib in $ALL_MISSING_LIBS - do - if echo $REQUIRED_LIBS | grep -q $lib - then - MISSING_LIBS="$MISSING_LIBS $lib" - fi - done - if [ "$MISSING_LIBS" != "" ] - then - echo "obj $FILE" >>$LLIST.3_rebuild - if $SEARCH_BROKEN ; then - echo_v " broken $FILE (requires ${MISSING_LIBS})" - else - echo_v " found $FILE" - fi - fi - fi - fi - done - if $SEARCH_BROKEN ; then - # Look for missing version - for FILE in $(grep "no version information available" $LLIST.3_ldd_errors | awk '{print $NF}' | sed 's/[()]//g' | sort -u) ; do - echo "obj $FILE" >>$LLIST.3_rebuild - echo_v " broken $FILE (no version information available)" - done - # Look for broken .la files - cat $LIST.1_files | egrep '*\.la$' | while read FILE ; do - for depend in $(grep '^dependency_libs' $FILE | awk -F'=' '{print $2}' | sed "s/'//g") ; do - [ ${depend:0:1} != '/' ] && continue - if [ ! -e $depend ] ; then - echo "obj $FILE" >>$LLIST.3_rebuild - echo_v " broken $FILE (requires ${depend})" - fi - done - done - fi - 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*" - echo -n >$LLIST.4_packages_raw - echo -n >$LLIST.4_package_owners - cat $LLIST.3_rebuild | while read obj FILE ; do - if $PORTAGE_UTILS ; then - EXACT_PKG="$(qfile -qvC ${FILE} )" - else - EXACT_PKG=$(find /var/db/pkg -name CONTENTS | xargs fgrep -l "obj $FILE " | sed -e 's:/var/db/pkg/\(.*\)/CONTENTS:\1:g') - fi - # Ugly sed hack to strip version information - PKG="$(echo $EXACT_PKG | sed 's/-r[0-9].*$//;s/\(^.*\/*\)-.*$/\1/')" - 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 "$EXACT_PKG" >> $LLIST.4_packages_raw - echo "$FILE -> $EXACT_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.4_packages ] ; then - echo " using existing $LLIST.4_packages." - else - sort -u $LLIST.4_packages_raw >$LLIST.4_packages - echo -e " done.\n ($LLIST.4_packages)" - fi - - echo - echo -n -e "${GR}Assigning packages to ebuilds...${NO}" - if [ -f $LLIST.4_ebuilds ] ; then - echo " using existing $LLIST.4_ebuilds." - else - if [ -s "$LLIST.4_packages" ] - then - set_trap "$LLIST.4_ebuilds" - cat $LLIST.4_packages | while read EXACT_PKG - do - PKG="$(echo $EXACT_PKG | sed 's/-r[0-9].*$//;s/\(^.*\/*\)-.*$/\1/')" - SLOT=$(cat /var/db/pkg/${EXACT_PKG}/SLOT) - best_visible=$(portageq best_visible $PORTAGE_ROOT ${PKG}:${SLOT}) - [ "x" != "x$best_visible" ] && echo $best_visible - done > $LLIST.4_ebuilds - echo -e " done.\n ($LLIST.4_ebuilds)" - else - echo " Nothing to rebuild" - echo -n > $LLIST.4_ebuilds - fi - fi -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 - if [ -s "$LLIST.3_rebuild" ] ; then - set_trap "$LLIST.4_ebuilds" - find /var/db/pkg -name CONTENTS | xargs fgrep -l -f $LLIST.3_rebuild | - sed 's:/var/db/pkg/\(.*\)/CONTENTS:\1:' > $LLIST.4_ebuilds - echo -e " done.\n ($LLIST.4_ebuilds)" - else - echo " Nothing to rebuild" - echo -n > $LLIST.4_ebuilds - fi - fi - -fi - -echo -echo -n -e "${GR}Evaluating package order...${NO}" -if [ -f $LLIST.5_order ] ; then - echo " using existing $LLIST.5_order." -else - set_trap "$LLIST.5_order" - RAW_REBUILD_LIST="$(cat $LLIST.4_ebuilds | sed s/^/=/ | tr '\n' ' ')" - if [ ! -z "$RAW_REBUILD_LIST" ] ; then - REBUILD_GREP="^\\($( (EMERGE_DEFAULT_OPTS="" emerge --nospinner --pretend --oneshot --nodeps --quiet $RAW_REBUILD_LIST ; echo $? >$LLIST.5a_status ) | sed -n 's/\./\\&/g;s/ //g;s/$/\\/;s/\[[^]]*\]//gp' | tr '\n' '|' | sed 's/|$//'))\$" - if [ $(cat $LLIST.5a_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 "- An ebuild is no longer in the portage tree." - echo "- An ebuild is masked, use /etc/portage/packages.keyword" - echo " and/or /etc/portage/package.unmask to unmask it" - for i in . . . . . ; do - echo -n -e '\a.' - sleep 1 - done - ln -f $LLIST.4_ebuilds $LLIST.5_order - else - (EMERGE_DEFAULT_OPTS="" emerge --nospinner --pretend --oneshot --deep --quiet $RAW_REBUILD_LIST ; echo $? >$LLIST.5b_status ) | sed -n 's/ *$//;s/^\[.*\] //p' | awk '{print $1}' | grep "$REBUILD_GREP" >$LLIST.5_order - if [ $(cat $LLIST.5b_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 "- An ebuild is no longer in the portage tree." - echo "- An ebuild is masked, use /etc/portage/packages.keyword" - echo " and/or /etc/portage/package.unmask to unmask it" - for i in . . . . . ; do - echo -n -e '\a.' - sleep 1 - done - rm -f $LLIST.5_order - ln -f $LLIST.4_ebuilds $LLIST.5_order - fi - fi - else - echo -n "" >$LLIST.5_order - fi - echo -e " done.\n ($LLIST.5_order)" -fi - -# Clean up no longer needed environment variables -unset COMPLETE_LD_LIBRARY_PATH SEARCH_DIRS SEARCH_DIRS_MASK LD_LIBRARY_MASK PORTAGE_ROOT CALLED_OPTIONS - -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} " - if [ ! $KEEPTEMP ] - then - rm $LIST.[0-2]_* - rm $LLIST.[3-9]_* - fi - exit 0 -fi - -IS_REAL_MERGE=true -echo " $EMERGE_OPTIONS " | grep -q '\( -p \| --pretend \| -f \| --fetchonly \)' && IS_REAL_MERGE=false - -echo -echo -e "${GR}All prepared. Starting rebuild...${NO}" - -echo "emerge --oneshot $EMERGE_OPTIONS $REBUILD_LIST" - -if $IS_REAL_MERGE ; then - for i in . . . . . . . . . . ; do - echo -n -e '\a.' - sleep 1 - done - echo -fi - -# Link file descriptor #6 with stdin -exec 6<&0 - -# Run in background to correctly handle Ctrl-C -( - EMERGE_DEFAULT_OPTS="" emerge --oneshot $EMERGE_OPTIONS $REBUILD_LIST <&6 - echo $? >$LLIST.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 $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}revdep-rebuild failed to emerge all packages${NO}" - echo -e "${RD}you have the following choices:${NO}" - echo - echo "- if emerge failed during the build, fix the problems and re-run revdep-rebuild" - echo " or" - echo "- use -X or --package-names as first argument (trys to rebuild package, not exact" - echo " ebuild)" - echo " or" - echo "- set ACCEPT_KEYWORDS=\"~<your platform>\" 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*.?_*" - exit $(cat $LLIST.6_status) -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} " - echo - rm $LIST.[0-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 -exit 0 diff --git a/src/revdep-rebuild/revdep-rebuild-sh b/src/revdep-rebuild/revdep-rebuild-sh deleted file mode 100755 index c7acdc6..0000000 --- a/src/revdep-rebuild/revdep-rebuild-sh +++ /dev/null @@ -1,332 +0,0 @@ -#!/bin/sh -# Copyright 1999-2007 Gentoo Foundation -# Distributed under the terms of the GNU General Public License v2 - -appname=${0##*/} - -# If baselayout is broken, define our own functions -[ -r /etc/init.d/functions.sh ] && . /etc/init.d/functions.sh -if ! type eend >/dev/null 2>&1 || ! eend 0 >/dev/null 2>&1; then - einfo() { echo " * $*"; } - eerror() { echo " * $*" >&2; return 1; } - eindent() { :; } - eoutdent() { :; } -fi - -# No temporary files used, so nothing to clean up :) -trap "export RC_EINDENT=; echo; eerror 'Caught interrupt'; exit 1" \ - SIGINT SIGQUIT - -print_usage() { - cat << EOF -Usage: ${appname} [OPTIONS] [--] [EMERGE_OPTIONS] - -Broken reverse dependency rebuilder. - - -h, --help Print this usage - -e, --exact Emerge based on exact package version - -C, --nocolor Turn off colored output - -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 <http://bugs.gentoo.org> -EOF -} - -# Have we linked to this library? -elf_linked() { - local f=$1 - shift - while [ -n "$1" ]; do - ldd "${f}" 2>/dev/null | grep -q "=> $1 " && return 0 - shift - done - return 1 -} - -# Work out of we really need this library or not -elf_needed() { - local f=$1 - shift - while [ -n "$1" ]; do - objdump -p "${f}" 2>/dev/null | \ - grep -vF "${ld_mask:=$'\a'}" | \ - grep -q "^ NEEDED ${1##*/}" && return 0 - shift - done - return 1 -} - -elf_broken() { - local lib= - - for lib in $(ldd "$1" 2>/dev/null | \ - sed -n -e 's/[[:space:]]*\(.*\) => not found.*/\1/p'); do - if elf_needed "$1" "${lib}"; then - echo "(missing ${lib})" - return 0 - fi - done - return 1 -} - -# Check that all direct files exist in .la files -la_broken() { - local x= - for x in $(sed -n -e "s/^dependency_libs=\'\(.*\)'\$/\1/p" "$1"); do - case "${x}" in - /*) - if [ ! -e "${x}" ]; then - echo "(missing ${x})" - return 0 - fi - ;; - esac - done - - return 1 -} - -# Return a $PATH style variable based on ld.so.conf -read_so_conf() { - local line= - while read line; do - case "${line}" in - "#"*) ;; - *) printf ":%s" "${line}";; - esac - done < /etc/ld.so.conf -} - -# Check to see if we have already scanned a dir or not -scanned() { - local dir=$1 IFS=: - set -- ${scanned} - - while [ -n "$1" ]; do - [ "$1" = "$dir" ] && return 0 - shift - done - - scanned="${scanned}${scanned:+:}${dir}" - return 1 -} - -# Hit the portage vdb to work out our ebuilds -# If everything is 100% then this happens in one very fast pass -# Otherwise we have to take the slow approach to inform the user which files -# are orphans -get_exact_ebuilds() { - local regex= ebuilds= x= IFS=: - set -- $@ - IFS=" " - - # Hit the vdb in one go - this is fast! - regex=$(printf "%s|" "$@") - regex=${regex%*|} - find /var/db/pkg -name CONTENTS | \ - xargs egrep "^obj (${regex}) " | \ - sed -e 's,/var/db/pkg/\(.*\/.*\)/CONTENTS:.*,=\1,g' | \ - tr '\n' ' ' -} - -# Get our args -libs= -exact=false -order=true -while [ -n "$1" ]; do - case "$1" in - --*=*) - arg1=${1%%=*} - arg2=${1#*=} - shift - set -- ${arg1} ${arg2} $@ - continue - ;; - -h|--help) print_usage; exit 0;; - -L|--library|--soname|--soname-regexp) - if [ -z "$2" ]; then - eerror "Missing expected argument to $1" - exit 1 - fi - libs="${libs}${libs:+ }$2" - shift - ;; - -e|--exact) exact=true;; - -X|--package-names) ;; #compat - --) shift; emerge_opts="$@"; break;; - *) eerror "$0: unknown option $1"; exit 1;; - esac - shift -done - -einfo "Configuring search environment for ${appname}" -# OK, this truely sucks. Paths can have spaces in, but our config format -# is space separated? -sdirs=$(unset SEARCH_DIRS; portageq envvar SEARCH_DIRS) -sdirs_mask=$(unset SEARCH_DIRS_MASK; portageq envvar SEARCH_DIRS_MASK) -ld_mask=$(unset LD_LIBRARY_MASK; portageq envvar LD_LIBRARY_MASK) - -if [ -d /etc/revdep-rebuild ]; then - for x in /etc/revdep-rebuild/*; do - sdirs="${sdirs}${sdirs:+ }$(unset SEARCH_DIRS; . "${x}"; echo "${SEARCH_DIRS}")" - sdirs_mask="${sdirs_mask}${sdirs_mask:+ }$(unset SEARCH_DIRS_MASK; . "${x}" ; echo "${SEARCH_DIRS_MASK}")" - ld_mask="${ld_mask}${ld_mask:+ }$(unset LD_LIBRARY_MASK; . "${x}"; echo "${LD_LIBRARY_MASK}")" - done -else - sdirs="${sdirs}${sdirs:+ }/bin /sbin /usr/bin /usr/sbin /lib* /usr/lib*" - sdirs_mask="${sdirs_mask}${sdirs_mask:+ }/opt/OpenOffice /usr/lib/openoffice" - ld_mask="${ld_mask}${ld_mask:+ }libodbcinst.so libodbc.so libjava.so libjvm.so" -fi - -sdirs=$(find ${sdirs} -type d) - -einfo "Starting scan" -eindent -# Mark our masked dirs already scanned -scanned= -for dir in ${sdirs_mask}; do - scanned "${dir}" -done - -# Now scan our dirs -for dir in ${sdirs}; do - scanned "${dir}" && continue - - einfo "in ${dir}" - eindent - for x in "${dir}"/*; do - [ -d "${x}" ] && continue - [ -L "${x}" ] && continue - - scan=true - process=false - reason= - case "${x}" in - *.so|*.so.*) process=true;; - *.la) - scan=false - if [ -z "${libs}" ]; then - reason=$(la_broken "${x}") - [ $? = 0 ] && process=true - fi - ;; - esac - [ -x "${x}" ] && ${scan} && process=true - ${process} || continue - - if ${scan}; then - process=false - if [ -n "${libs}" ]; then - for lib in ${libs}; do - if [ "${lib#/}" != "${lib}" ]; then - # If lib starts with / then check if the exact - # lib is linked - elf_linked "${x}" "${lib}" || continue - fi - if elf_needed "${x}" ${lib}; then - process=true - break - fi - done - else - reason=$(elf_broken "${x}") - [ $? = 0 ] && process=true - fi - fi - - ${process} || continue - einfo "found ${x} ${reason}" - files="${files}${files:+:}${x}" - done - eoutdent -done -eoutdent - -if [ -z "${files}" ]; then - if [ -z "${libs}" ]; then - einfo "Nothing found that needs rebuilding" - else - einfo "No dynamic binaries found with these libraries" - fi - exit 0 -fi - -einfo "Assigning files to packages" -eindent -ebuilds=$(get_exact_ebuilds "${files}") - -if [ -z "${ebuilds}" ]; then - eerror "No packages own these files" - exit 1 -fi - -# Work out the best visible package for the slot -if ! ${exact}; then - root=$(portageq envvar ROOT) - root=${root:-/} - - set -- ${ebuilds} - ebuilds= - for x in "$@"; do - x=${x#=*} - pkg=${x%-r[0-9]*} - pkg=${pkg%-*} - slot=$(cat "/var/db/pkg/${x}/SLOT") - ebd=$(portageq best_visible "${root}" "${pkg}:${slot}") - if [ -z "${ebd}" ]; then - eerror "Cannot find an ebuild visible for ${x}" - else - ebuilds="${ebuilds}${ebuilds:+ }=${ebd}" - fi - done -fi -eoutdent - -# Work out the build order -if ${order}; then - einfo "Ordering packages" - order="$(EMERGE_DEFAULT_OPTS="" \ - emerge --nospinner --pretend --deep --quiet ${ebuilds})" - if [ $? = 0 ]; then - ebuilds=$(echo "${order}" | \ - sed -e 's:^\[.*\] \([^ ]*\)[ ].*$:=\1:' | \ - grep -F "$(printf "%s\n" ${ebuilds})" | \ - tr '\n' ' ') - else - eerror "Unable to order packages!" - fi -fi - -if [ -z "${ebuilds}" ]; then - eerror "Don't know how to find which package owns what file :/" - exit 1 -fi - -echo -einfo "About to execute" -echo "emerge --oneshot ${emerge_opts} ${ebuilds}" -echo - -i=5 -printf "in" -while [ ${i} -gt 0 ]; do - printf " ${i}" - sleep 1 - i=$((${i} - 1)) -done -printf "\n\n" - -EMERGE_DEFAULT_OPTS="" emerge --oneshot ${emerge_opts} ${ebuilds} -retval=$? - -if [ "${retval}" = 0 ]; then - einfo "All done" - exit 0 -fi - -eerror "There was an error trying to emerge the broken packages" -exit "${retval}" diff --git a/src/revdep-rebuild/revdep-rebuild.1 b/src/revdep-rebuild/revdep-rebuild.1 deleted file mode 100644 index bcf1e26..0000000 --- a/src/revdep-rebuild/revdep-rebuild.1 +++ /dev/null @@ -1,138 +0,0 @@ -.TH "revdep\-rebuild" "1" "" "gentoolkit" "" -.SH "NAME" -revdep\-rebuild \- Gentoo: Reverse Dependency Rebuilder -.SH "SYNOPSIS" -.B revdep\-rebuild -[OPTIONS] [\-\-] [EMERGE OPTIONS] -.SH "DESCRIPTION" -revdep\-rebuild scans libraries and binaries for missing shared library dependencies and attempts to fix them by re\-emerging those broken binaries and shared libraries. It is useful when an upgraded package breaks other software packages that are dependent upon the upgraded package. -.SH "OPTIONS" -.TP -.B \-C | \-\-nocolor -Turn off colored output. (This option is also passed to portage.) -.TP -.B \-e | \-\-exact -Emerge the most recent version of found packages, without regard to SLOT. -.TP -.B \-h | \-\-help -Print usage. -.TP -.B \-i | \-\-ignore -Delete temporary files from previous runs. -.TP -.B \-k | \-\-keep\-temp -Force revdep\-rebuild not to delete temporary files after it successfully rebuilds packages. This option will NOT prevent revdep\-rebuild from deleting inconsistent or out\-of\-date temporary files. -.TP -.B \-\-library NAME | -L NAME -Search for reverse dependencies for a particular library or group of libraries, rather than every library on the system. Emerge packages that use the named library. NAME can be a full path to a library or basic regular expression. (See regex(7).) -.TP -.B \-l | \-\-no\-ld\-path -Do not set LD_LIBRARY_PATH. \fBNote:\fR Using this option will cause revdep-rebuild to report some false positives. -.TP -.B \-o | \-\-no-order -Do not check the build order against the deep dependency list. This will make revdep-rebuild faster, but it can cause emerge failures. Please try revdep\-rebuild without \-o before reporting any bugs. -.TP -.B \-p | \-\-pretend -Do a dry-run. Do not delete temporary files. (\-k \-p is redundant, but harmless.) \-\-pretend is assumed when not running revdep\-rebuild as root. -.TP -.B \-P | \-\-no\-progress -Turn off the progress meter -.TP -.B \-q | \-\-quiet -Print less output and disable the progress meter. (This option is also passed to portage.) -.TP -.B \-u UTIL | \-\-no-util UTIL -Do not use features provided by UTIL. -UTIL can be one of portage-utils or pkgcore, or it can be a \fBquoted\fR space-delimited list. -.TP -.B \-v | \-\-verbose -More output. (Prints the revdep\-rebuild search environment.) -.TP -.B All other options (including unrecognized ones) are passed to the emerge command. Single\-letter options may not be combined, so for example, \-pv is not valid. Please use \-p \-v. -.SH "CONFIGURATION" -revdep\-rebuild no longer uses hardcoded paths. To change the default behavior the following variables can be changed by the user. - -LD_LIBRARY_MASK \- Mask of specially evaluated libraries -.LP -SEARCH_DIRS \- List of directories to search for executables and libraries -.LP -SEARCH_DIRS_MASK \- List of directories to not search - -You can prepend to these variables by setting the variable in your environment prior to execution, by placing an entry in /etc/make.conf, or by placing a file in /etc/revdep\-rebuild containing the appropriate variables. - -The variables are read and set in the following order: - -environment settings \- one time changes by user -.br -/etc/make.conf \- persistent changes by user -.br -/etc/revdep\-rebuild/* \- persistent changes by ebuild authors - -While a user can edit and modify the files in the /etc/revdep\-rebuild directory, please be aware that the /etc/revdep\-rebuild directory is not under configuration protection and files can be removed and/or overwritten by an ebuild. To change this add /etc/revdep\-rebuild to the CONFIG_PROTECT variable in /etc/make.conf. - -An entry of "\-*" means to clear the variable from that point forward. -Example: SEARCH_DIRS="/usr/bin \-*" will set SEARCH_DIRS to contain only /usr/bin - -revdep\-rebuild honors the NOCOLOR and PORTAGE_NICENESS variables from /etc/make.conf -.SH "EXAMPLES" -It is recommended that when running revdep\-rebuild that the following command be used initially: -.br -\fBrevdep\-rebuild \-\-ignore \-\-pretend\fR - -To search the entire system, while excluding /mnt and /home: -.br -\fBenv SEARCH_DIRS="/ \-*" SEARCH_DIRS_MASK="/mnt /home" revdep\-rebuild\fR - -To rebuild packages that depend on libkdecore.so.4 from KDE 3.3: -.br -\fBrevdep\-rebuild \-\-library /usr/kde/3.3/lib/libkdecore.so.4\fR - -To rebuild packages that depend upon libImlib.so and libImlib2.so: -.br -\fBrevdep\-rebuild \-\-library libImlib[2]*.so.*\fR - -.SH "FILES" -.P -revdep\-rebuild keeps several pseudo-temporary files in /var/cache/revdep\-rebuild/. Deleting these files can improve accuracy at the cost of speed: -.TP 15 -.I 0_env.rr -Contains environment variables -.TP -.I 1_files.rr -Contains a list of files to search -.TP -.I 2_ldpath.rr -Contains the LDPATH -.TP -.I 3_broken.rr -Contains the list of broken files -.TP -.I 3_errors.rr -Contains the ldd error output -.TP -.I 4_raw.rr -Contains the raw list of packages -.TP -.I 4_owners.rr -Contains the file owners -.TP -.I 4_pkgs.rr -Contains the unsorted bare package names -.TP -.I 4_ebuilds.rr -Contains the unsorted atoms -.TP -.I 5_order.rr -Contains the sorted atoms -.TP -.I 6_status.rr -Contains the ldd error output - -.SH "EXIT STATUS" -revdep\-rebuild returns a zero exit status if it \fBand emerge\fR succeeds, and a nonzero exit status otherwise. -.SH "BUGS" -.LP -Report bugs to <http://bugs.gentoo.org>. Please do not report emerge failures caused by \-o or \-e. Please include your .revdep\-rebuild* files, your emerge \-\-info, and patches. ;) - -.SH "SEE ALSO" -emerge(1), portage(5), regex(7) |
