Merged from trunk -r12040:12057
authorFabian Groffen <grobian@gentoo.org>
Mon, 1 Dec 2008 20:56:01 +0000 (20:56 -0000)
committerFabian Groffen <grobian@gentoo.org>
Mon, 1 Dec 2008 20:56:01 +0000 (20:56 -0000)
   | 12041   | Add some hints about bash binary corruption and hardware     |
   | zmedico | malfunction to the message that's displayed when bash exits  |
   |         | unexpectedly.                                                |

   | 12043   | Add new @unavailable package set which contains all          |
   | zmedico | installed packages for which there are no visible ebuilds    |
   |         | corresponding to the same $CATEGORY/$PN:$SLOT.               |

   | 12044   | Add back accidentally removed @downgrade set. Thanks to      |
   | zmedico | Arfrever.                                                    |

   | 12045   | When displaying anscestors of an unstatisfied dependency     |
   | zmedico | (code from bug #245358), avoid a potential infinite loop and |
   |         | memory leak triggered by circular dependencies. Thanks to    |
   |         | Peter Weller <welp@g.o> for reporting.                       |

   | 12047   | Add docs for all of the supported commands.                  |
   | zmedico |                                                              |

   | 12049   | Bug #247548 - Remove 'last' and 'lfull' commands since       |
   | zmedico | nobody uses them. Thanks to Alec Warner <antarus@g.o>.       |

   | 12051   | Fix the code from bug #245358 so that it's guaranteed to     |
   | zmedico | traverse all the way to a root node, even when circular deps |
   |         | are encountered.                                             |

   | 12053   | Bug #188780 - Make the read_int() function show a more human |
   | zmedico | readable error message, instead of the 'value too great for  |
   |         | base' message when the user enters an invalid value such as  |
   |         | '1y'.                                                        |

   | 12055   | Fix SIGINT and SIGTERM trap handling so the temp dir always  |
   | zmedico | cleaned up when killed.                                      |

   | 12057   | Add a note about negative IUSE default settings being        |
   | zmedico | ineffective given the default USE_ORDER setting which causes |
   |         | profile and user configuration settings to override them.    |

svn path=/main/branches/prefix/; revision=12130

12 files changed:
bin/emaint
bin/etc-update
bin/repoman
cnf/sets.conf
doc/config/sets.docbook
man/ebuild.5
man/emaint.1
man/repoman.1
pym/_emerge/__init__.py
pym/portage/__init__.py
pym/portage/sets/dbapi.py
pym/repoman/utilities.py

index c5135212b2b64a6c0095b4bf9b3071458a677643..8ec7cadd34c97aa68e874eb1a0a6a218a7b972bf 100755 (executable)
@@ -4,6 +4,7 @@ import os
 import re
 import signal
 import sys
+import textwrap
 import time
 from optparse import OptionParser, OptionValueError
 
@@ -20,6 +21,8 @@ import portage.const, portage.exception, portage.output
 
 class WorldHandler(object):
 
+       short_desc = "Fix problems in the world file"
+
        def name():
                return "world"
        name = staticmethod(name)
@@ -105,6 +108,8 @@ class WorldHandler(object):
 
 class BinhostHandler(object):
 
+       short_desc = "Generate a metadata index for binary packages"
+
        def name():
                return "binhost"
        name = staticmethod(name)
@@ -317,6 +322,9 @@ class MoveHandler(object):
                return errors
 
 class MoveInstalled(MoveHandler):
+
+       short_desc = "Perform package move updates for installed packages"
+
        def name():
                return "moveinst"
        name = staticmethod(name)
@@ -325,6 +333,9 @@ class MoveInstalled(MoveHandler):
                MoveHandler.__init__(self, portage.db[myroot]["vartree"])
 
 class MoveBinary(MoveHandler):
+
+       short_desc = "Perform package move updates for binary packages"
+
        def name():
                return "movebin"
        name = staticmethod(name)
@@ -409,6 +420,9 @@ class ProgressHandler(object):
                raise NotImplementedError(self)
 
 class CleanResume(object):
+
+       short_desc = "Discard emerge --resume merge lists"
+
        def name():
                return "cleanresume"
        name = staticmethod(name)
@@ -485,12 +499,20 @@ def emaint_main(myargv):
                setattr(parser, var, str(option))
 
 
-       usage = "usage: emaint [options] " + " | ".join(module_names)
+       usage = "usage: emaint [options] COMMAND"
 
-       usage+= "\n\nCurrently emaint can only check and fix problems with one's world\n"
-       usage+= "file.  Future versions will integrate other portage check-and-fix\n"
-       usage+= "tools and provide a single interface to system health checks."
+       desc = "The emaint program provides an interface to system health " + \
+               "checks and maintenance. See the emaint(1) man page for " + \
+               "for additional information about the following commands:"
 
+       usage += "\n\n"
+       for line in textwrap.wrap(desc, 65):
+               usage += "%s\n" % line
+       usage += "\n"
+       usage += "  %s" % "all".ljust(15) + \
+               "Perform all supported commands\n"
+       for m in module_names[1:]:
+               usage += "  %s%s\n" % (m.ljust(15), modules[m].short_desc)
 
        parser = OptionParser(usage=usage, version=portage.VERSION)
        parser.add_option("-c", "--check", help="check for problems",
index a9b056831597b9e9b48e9c56fd88b12d80091d62..0a0f829c3f6c458e8a3b617eda280ea99cf1338a 100755 (executable)
@@ -223,7 +223,8 @@ read_int() {
                read my_input
                # failed integer conversions will break a loop unless they're enclosed
                # in a subshell.
-               echo "${my_input}" | ( declare -i x; read x) && break
+               echo "${my_input}" | ( declare -i x; read x) 2>/dev/null && break
+               echo -n "Value '$my_input' is not valid. Please enter an integer value:" >&2
        done
        echo ${my_input}
 }
@@ -445,10 +446,9 @@ Please select from the menu above (-1 to exit, losing this merge): "
 }
 
 die() {
-       trap "" TERM
-       trap "" KILL
+       trap SIGTERM SIGINT
 
-       if [ ${2} -eq 0 ]; then
+       if [ "$2" -eq 0 ]; then
                echo "Exiting: ${1}"
                scan > /dev/null
                [ ${count} -gt 0 ] && echo "NOTE: ${count} updates remaining"
@@ -500,7 +500,8 @@ export PORTAGE_TMPDIR
 export EROOT=${ROOT%/}${EPREFIX}/
 
 TMP="${PORTAGE_TMPDIR}/etc-update-$$"
-trap die term
+trap "die terminated 1" SIGTERM
+trap "die interrupted 1" SIGINT
 
 [ -w ${PORTAGE_CONFIGROOT}etc ] || die "Need write access to ${PORTAGE_CONFIGROOT}etc" 1
 #echo $PORTAGE_TMPDIR
index e3148d97270c7f69b9aba1a78e0c8f4d76e61434..43fc033da9d98242c8451d1d9a5d6802db000869 100755 (executable)
@@ -25,11 +25,6 @@ import platform
 from itertools import chain, izip
 from stat import S_ISDIR, ST_CTIME
 
-try:
-       import cPickle as pickle
-except ImportError:
-       import pickle
-
 try:
        import cStringIO as StringIO
 except ImportError:
@@ -149,8 +144,6 @@ def ParseArgs(args, qahelp):
                'fix' : 'Fix simple QA issues (stray digests, missing digests)',
                'full' : 'Scan directory tree and print all issues (not a summary)',
                'help' : 'Show this screen',
-               'last' : 'Remember report from last run',
-               'lfull' : 'Remember report from last run (full listing)',
                'manifest' : 'Generate a Manifest (fetches files if necessary)',
                'scan' : 'Scan directory tree for QA issues' 
        }
@@ -226,7 +219,7 @@ def ParseArgs(args, qahelp):
                                break
 
        if not opts.mode:
-               opts.mode = 'full'      #default to full
+               opts.mode = 'full'
        
        if opts.mode == 'ci':
                opts.mode = 'commit'  # backwards compat shortcut
@@ -424,61 +417,8 @@ suspect_rdepend = frozenset([
 # file.executable
 no_exec = frozenset(["Manifest","ChangeLog","metadata.xml"])
 
-def last(full=False):
-       """Print the results of the last repoman run
-       Args:
-               full - Print the complete results, if false, print a summary
-       Returns:
-               Doesn't return (invokes sys.exit()
-       """
-       #Retrieve and unpickle stats and fails from saved files
-       savedf=open(os.path.join(portage.const.CACHE_PATH, 'repo.stats'),'r')
-       stats = pickle.load(savedf)
-       savedf.close()
-       savedf=open(os.path.join(portage.const.CACHE_PATH, 'repo.fails'),'r')
-       fails = pickle.load(savedf)
-       savedf.close()
-
-       #dofail will be set to 1 if we have failed in at least one non-warning category
-       dofail=0
-       #dowarn will be set to 1 if we tripped any warnings
-       dowarn=0
-       #dofull will be set if we should print a "repoman full" informational message
-       dofull=0
-
-       dofull = options.mode not in ("full", "lfull")
-       
-       for x in qacats:
-               if not stats[x]:
-                       continue
-               dowarn = 1
-               if x not in qawarnings:
-                       dofail = 1
-
-       print
-       print green("RepoMan remembers...")
-       print
-       style_file = ConsoleStyleFile(sys.stdout)
-       console_writer = StyleWriter(file=style_file, maxcol=9999)
-       console_writer.style_listener = style_file.new_styles
-       f = formatter.AbstractFormatter(console_writer)
-       utilities.format_qa_output(f, stats, fails, dofull, dofail, options, qawarnings)
-       print
-       if dofull:
-               print bold("Note: type \"repoman lfull\" for a complete listing of repomans last run.")
-               print
-       if dowarn and not dofail:
-               print green("RepoMan sez:"),"\"You only gave me a partial QA payment last time?\n              I took it, but I wasn't happy.\""
-       elif not dofail:
-               print green("RepoMan sez:"),"\"If everyone were like you, I'd be out of business!\""
-       print
-       sys.exit(0)
-
 options, arguments = ParseArgs(sys.argv, qahelp)
 
-if options.mode in ('last', 'lfull'):
-       last('lfull' in options.mode)
-
 # Set this to False when an extraordinary issue (generally
 # something other than a QA issue) makes it impossible to
 # commit (like if Manifest generation fails).
@@ -1608,24 +1548,12 @@ for x in scanlist:
 if options.mode == "manifest":
        sys.exit(dofail)
 
-#Pickle and save results for instant reuse in last and lfull
-if os.access(portage.const.CACHE_PATH, os.W_OK):
-       for myobj, fname in (stats, "repo.stats"), (fails, "repo.fails"):
-               fpath = os.path.join(portage.const.CACHE_PATH, fname)
-               savef = open(fpath, 'w')
-               pickle.dump(myobj, savef)
-               savef.close()
-               portage.apply_secpass_permissions(fpath, gid=portage.portage_gid,
-                       mode=0664)
-
-# TODO(antarus) This function and last () look familiar ;)
-
 #dofail will be set to 1 if we have failed in at least one non-warning category
 dofail=0
 #dowarn will be set to 1 if we tripped any warnings
 dowarn=0
 #dofull will be set if we should print a "repoman full" informational message
-dofull = options.mode not in ("full", "lfull")
+dofull = options.mode != 'full'
 
 for x in qacats:
        if not stats[x]:
index dd2ccb410dfe5f77e66eb07f26bfc862815b5b1e..0be4827bcbfac7a21de7b567dc0b297fdc38ffdd 100644 (file)
@@ -64,3 +64,9 @@ files = /lib/modules
 [downgrade]
 class = portage.sets.dbapi.DowngradeSet
 world-candidate = False
+
+# Installed packages for which there are no visible ebuilds
+# corresponding to the same $CATEGORY/$PN:$SLOT.
+[unavailable]
+class = portage.sets.dbapi.UnavailableSet
+world-candidate = False
index d993024bd392151fe8caf13fe0b7673226e4f529..dc26b1a0c80665a6345ee2743d825d591ffdf222 100644 (file)
                </itemizedlist>
                </para>
                </sect2>
+               <sect2 id='config-set-classes-UnavailableSet'>
+               <title>portage.sets.dbapi.UnavailableSet</title>
+               <para>
+               Package set which contains all installed
+               packages for which there are no visible ebuilds
+               corresponding to the same $CATEGORY/$PN:$SLOT.
+               This class supports the following options:
+               <itemizedlist>
+               <listitem><varname>metadata-source</varname>: Optional, defaults to
+               "porttree". Specifies the repository to use for getting the metadata
+               to check.</listitem>
+               </itemizedlist>
+               </para>
+               </sect2>
                <sect2 id='config-set-classes-DowngradeSet'>
                <title>portage.sets.dbapi.DowngradeSet</title>
                <para>
        <listitem><varname>live-rebuild</varname>: uses <classname>VariableSet</classname></listitem>
        <listitem><varname>module-rebuild</varname>: uses <classname>OwnerSet</classname></listitem>
        <listitem><varname>downgrade</varname>: uses <classname>DowngradeSet</classname></listitem>
+       <listitem><varname>unavailable</varname>: uses <classname>UnavailableSet</classname></listitem>
        </itemizedlist>
        Additionally the default configuration includes a multi set section based on
        the <classname>StaticFileSet</classname> defaults that creates a set for each 
index 76cd27e68241aa3eb562dba6fe35f0aaa9436b68..d438addfb65fe1823ccd3c0efc997824c4993cf2 100644 (file)
@@ -196,7 +196,9 @@ arch related flags (see \fBKEYWORDS\fR). Beginning with \fBEAPI 1\fR, it
 is possible to prefix flags with + or - in order to create default settings
 that respectively enable or disable the corresponding \fBUSE\fR flags. For
 details about \fBUSE\fR flag stacking order, refer to the \fBUSE_ORDER\fR
-variable in \fBmake.conf\fR(5).
+variable in \fBmake.conf\fR(5). Given the default \fBUSE_ORDER\fR setting,
+negative IUSE default settings are ineffective since profile and user
+configuration settings override them.
 .TP
 \fBDEPEND\fR
 This should contain a list of all packages that are required for the
index 31624b2086bee045f0d5e8833e73b046c0c6d389..63854c02e2e8327a6d90288a135c2ed602f6eec7 100644 (file)
@@ -4,10 +4,32 @@ emaint \- performs system health checks and maintenance
 .SH SYNOPSIS
 .BR emaint
 [\fIoptions\fR]
-[\fBall\fR | \fBworld\fR]
+[\fBall\fR | \fBbinhost\fR | \fBcleanresume\fR | \
+\fBmovebin\fR | \fBmoveinst\fR | \fBworld\fR]
 .SH DESCRIPTION
-.B emaint
-checks for and fixes problems in the portage \fIworld\fR file.
+The emaint program provides an interface to system health
+checks and maintenance.
+.SH COMMANDS
+.TP
+.BR all
+Perform all supported commands.
+.TP
+.BR binhost
+Generate a metadata index for binary packages located in \fBPKGDIR\fR (for
+download by remote clients). See the \fBPORTAGE_BINHOST\fR documentation in
+the \fBmake.conf\fR(5) man page for additional information.
+.TP
+.BR cleanresume
+Discard merge lists saved for the \fBemerge\fR(1) \fB--resume\fR action.
+.TP
+.BR movebin
+Perform package move updates for binary packages located in \fBPKGDIR\fR.
+.TP
+.BR moveinst
+Perform package move updates for installed packages.
+.TP
+.BR world
+Fix problems in the \fIworld\fR file.
 .SH OPTIONS 
 .TP
 .B \-c, \-\-check
index 14165aae9d3a87a395c2c0724a35adbf595e18c3..c6d83d5cdce238fed00f15f34fa710a734409941 100644 (file)
@@ -59,9 +59,6 @@ Show this screen
 .B full
 Scan directory tree for QA issues (full listing)
 .TP
-.B last
-Remember report from last run
-.TP
 .B help
 Show this screen
 .TP
@@ -71,9 +68,6 @@ Scan directory tree for QA issues (short listing)
 .B fix
 Fix simple QA issues (stray digests, missing digests)
 .TP
-.B lfull
-Remember report from last run (full listing)
-.TP
 .B manifest
 Generate a Manifest (fetches files if necessary)
 .TP
index e758e8b352324b9ebea0e81312f83c4c85c0864f..a1e24b7b3e82dd557121b858e8e0691992209ed9 100644 (file)
@@ -5435,19 +5435,26 @@ class depgraph(object):
                        print "\nemerge: there are no ebuilds to satisfy "+green(xinfo)+"."
 
                # Show parent nodes and the argument that pulled them in.
+               traversed_nodes = set()
                node = myparent
                msg = []
                while node is not None:
+                       traversed_nodes.add(node)
                        msg.append('(dependency required by "%s" [%s])' % \
                                (colorize('INFORM', str(node.cpv)), node.type_name))
-                       parent = None
+                       # When traversing to parents, prefer arguments over packages
+                       # since arguments are root nodes. Never traverse the same
+                       # package twice, in order to prevent an infinite loop.
+                       selected_parent = None
                        for parent in self.digraph.parent_nodes(node):
                                if isinstance(parent, DependencyArg):
                                        msg.append('(dependency required by "%s" [argument])' % \
                                                (colorize('INFORM', str(parent))))
-                                       parent = None
+                                       selected_parent = None
                                        break
-                       node = parent
+                               if parent not in traversed_nodes:
+                                       selected_parent = parent
+                       node = selected_parent
                for line in msg:
                        print line
 
index a5bfd78b3e7b0b84ed4373ec5f56e28e29aaa109..12c303ebb84e285802070c68363ab9bbe3f6f442 100644 (file)
@@ -5179,7 +5179,9 @@ def _doebuild_exit_status_check(mydo, settings):
        "is known to be triggered " + \
        "by things such as failed variable " + \
        "assignments (bug #190128) or bad substitution " + \
-       "errors (bug #200313)."
+       "errors (bug #200313). This behavior may also be " + \
+       "triggered by a corrupt bash binary or a hardware " + \
+       "problem such as memory or cpu malfunction."
        return msg
 
 def _doebuild_exit_status_check_and_log(settings, mydo, retval):
index 877c45ceeca36b2856f0bf20fe811b546208003d..65d05a2aefe8572dea1f6d6982eadc5aa56f10f8 100644 (file)
@@ -179,6 +179,33 @@ class DowngradeSet(PackageSet):
 
        singleBuilder = classmethod(singleBuilder)
 
+class UnavailableSet(EverythingSet):
+
+       _operations = ["unmerge"]
+
+       description = "Package set which contains all installed " + \
+               "packages for which there are no visible ebuilds " + \
+               "corresponding to the same $CATEGORY/$PN:$SLOT."
+
+       def __init__(self, vardb, metadatadb=None):
+               super(UnavailableSet, self).__init__(vardb)
+               self._metadatadb = metadatadb
+
+       def _filter(self, atom):
+               return not self._metadatadb.match(atom)
+
+       def singleBuilder(cls, options, settings, trees):
+
+               metadatadb = options.get("metadata-source", "porttree")
+               if not metadatadb in trees:
+                       raise SetConfigError(("invalid value '%s' for option " + \
+                               "metadata-source") % (metadatadb,))
+
+               return cls(trees["vartree"].dbapi,
+                       metadatadb=trees[metadatadb].dbapi)
+
+       singleBuilder = classmethod(singleBuilder)
+
 class CategorySet(PackageSet):
        _operations = ["merge", "unmerge"]
        
index cee52186efc74010c17afa53fd5048647aa66468..6003deeac1bac006741c6e7b9b6bbdb7878e2b6d 100644 (file)
@@ -211,7 +211,7 @@ def format_qa_output(formatter, stats, fails, dofull, dofail, options, qawarning
        Returns:
                None (modifies formatter)
        """
-       full = options.mode in ("full", "lfull")
+       full = options.mode == 'full'
        # we only want key value pairs where value > 0 
        for category, number in \
                itertools.ifilter(lambda myitem: myitem[1] > 0, stats.iteritems()):