Index: /vendor/portage/current/ChangeLog
===================================================================
--- /vendor/portage/current/ChangeLog	(revision 3419)
+++ /vendor/portage/current/ChangeLog	(revision 3419)
@@ -0,0 +1,3823 @@
+=============================================================================
+2.1.2.7
+2007-05-06
+branches/2.1.2 revision 6495
+=============================================================================
+
+
+bin/ebuild.sh
+  6481 zmedico  For bug #177211, use chmod -R on the children of the current
+                directory in order to reduce the size of the argument list.
+                (trunk r6479:6480
+
+
+bin/emerge
+  6483 zmedico  Use match_from_list in order to potentially avoid more
+                blocks. (trunk r6481:6482)
+  6493 zmedico  Use shlex for better splitting of PORTAGE_RSYNC_OPTS and
+                PORTAGE_RSYNC_EXTRA_OPTS. (trunk r6491:6492)
+  6495 zmedico  Prevent blockers that are only partially resolvable by merge
+                order from accidentally being ignored. (trunk r6493:6494)
+
+
+pym/portage.py
+  6479 zmedico  For bug #175058, comment #15, expand all possible variables
+                in each argument. (trunk r6477:6478)
+  6488 zmedico  Use varexpand to expand FETCHCOMMAND and RESUMECOMMAND.
+                (trunk r6486:6487)
+  6491 zmedico  Use shlex for better splitting of FETCHCOMMAND. (trunk
+                r6489:6490)
+
+
+pym/portage_versions.py
+  6486 zmedico  For bug #171259, fix vercmp so that implicit _p0 is less than
+                explicit _p0. Thanks to TGL <degrenier@easyconnect.fr> for
+                the patch. (trunk r6484:6485)
+
+
+=============================================================================
+2.1.2.6
+2007-05-04
+branches/2.1.2 revision 6476
+=============================================================================
+
+
+bin/emerge
+  6445 zmedico  For bug #176305, validate the resume merge list before
+                attempting to verify the ebuild manifests. (trunk r6443:6444)
+  6447 zmedico  Fix up missing mymergelist variable from the previous commit.
+                (trunk r6445:6446)
+  6455 zmedico  For bug #176384, adjust config according to options of the
+                command being resumed. (trunk r6453:6454)
+  6474 zmedico  For bug #176765, when a new package is blocked by another one
+                that is being replaced, handle another case where the
+                conflict can be avoided. (trunk r6472:6473)
+
+
+bin/isolated-functions.sh
+pym/output.py
+  6468 zmedico  Fix eend so that it works properly on a standard BSD console.
+                Thanks to UberLord. (trunk r6466:6467)
+
+
+cnf/make.globals
+  6453 zmedico  For bug #175058, properly quote the variables in FETCHCOMMAND
+                and RESUMECOMMAND since the command is spawned in a bash
+                shell. (trunk r6451:6452)
+  6457 zmedico  For bug #175058, avoid potential quoting issues by spawning
+                FETCHCOMMAND without a shell. (trunk r6455:6456)
+
+
+man/ebuild.1
+  6476 zmedico  document the behavior of `ebuild` wrt FEATURES=noauto #175444
+                (trunk r6470:6471)
+
+
+man/make.conf.5
+  6448 zmedico  In the installsources docs, note that CFLAGS needs to be set
+                to include debug information. Thanks to tigger^ for
+                reporting. (trunk r6441:6442)
+
+
+pym/portage.py
+  6457 zmedico  For bug #175058, avoid potential quoting issues by spawning
+                FETCHCOMMAND without a shell. (trunk r6455:6456)
+
+
+=============================================================================
+2.1.2.5
+2007-04-26
+branches/2.1.2 revision 6441
+=============================================================================
+
+
+bin/ecompressdir
+  6430 zmedico  Use portable sh syntax rather than bash syntax. Thanks to
+                drizzt. (trunk r6428:6429)
+
+
+bin/emerge
+  6418 zmedico  For bug #175344, use cp_list instead of xmatch in order to
+                avoid dep_expand calls. (trunk r6416:6417)
+  6420 zmedico  For bug #175344, handle a potential InvalidDependString
+                exception when parsing PROVIDE. (trunk r6418:6419)
+
+
+bin/repoman
+  6422 zmedico  For bug #175344, handle a potential InvalidDependString
+                exception when parsing PROVIDE. (trunk r6420:6421)
+
+
+pym/portage.py
+  6424 zmedico  For bug #175344, validate LICENSE and PROVIDE inside
+                doebuild(). (trunk r6422:6423)
+  6426 zmedico  Also validate SRC_URI inside doebuild(). (trunk r6424:6425)
+  6428 zmedico  Also validate RESTRICT inside doebuild(). (trunk r6426:6427)
+  6433 zmedico  For bug #175781, add a higher preference priority for choices
+                where all matching slots are installed (not just any slot).
+                (trunk r6431:6432)
+  6439 zmedico  For bug #176139, only symlink the distfiles that are required
+                according the current USE settings. (trunk r6437:6438)
+  6441 zmedico  Always ensure permissions in DISTCC_DIR in order to try to
+                prevent potential permission problems for non-root users who
+                are in the portage group (userpriv, etc.). (trunk r6439:6440)
+
+
+=============================================================================
+2.1.2.4
+2007-04-15
+branches/2.1.2 revision 6414
+=============================================================================
+
+
+bin/dohard
+  6397 zmedico  create leading directories to match behavior of other do*
+                programs (trunk r6393:6394 and r6395:6396)
+
+
+bin/doins
+  6404 zmedico  revise tests so that does not trigger an error (trunk
+                r6400:6401)
+  6405 zmedico  misc style fixes (trunk r6400:6401)
+
+
+bin/ebuild.sh
+bin/emerge-webrsync
+bin/etc-update
+bin/prepall
+bin/prepstrip
+bin/sed
+  6414 zmedico  convert `type -p` to `type -P` as noted by grobian (trunk
+                r6410:6411)
+
+
+bin/ecompressdir
+  6389 zmedico  Use relative paths inside ecompressdir in order to avoid
+                'Argument list too long' errors with large file sets
+                (observed when installing sys-apps/man-pages). (trunk
+                r6387:6388)
+
+
+bin/emerge
+  6340 zmedico  Punt the sorted_versions() function in favor of
+                list.sort(vercmp). (trunk r6338:6339)
+
+
+bin/misc-functions.sh
+  6393 zmedico  simplify unsafe file checking so files/paths with spaces dont
+                cause troubles (trunk r6391:6392)
+  6414 zmedico  convert `type -p` to `type -P` as noted by grobian (trunk
+                r6410:6411)
+
+
+bin/prepman
+  6363 zmedico  For bug #173808, compress ${mandir} all in one go instead of
+                doing subdirectories separately. This allows symlinks that
+                point into sibling directories to get updated properly by
+                ecompressdir. (trunk r6361:6362)
+  6372 zmedico  For bug #173808, add back the old heuristics to make sure
+                that we don't just blindly compress the contents of any
+                directory named "man".
+
+
+man/ebuild.5
+  6373 zmedico  remove references to DOCDESTTREE and INSDESTTREE (trunk
+                r6345:6346)
+  6376 zmedico  remove references to EXEDESTTREE (trunk r6349:6350)
+  6382 zmedico  cleanup example ebuild to be more representative of a good
+                ebuild #174260 by Timothy Redaelli (trunk r6378:6379)
+  6398 zmedico  document new version suffix style #166522 (trunk r6394:6395)
+
+
+man/emerge.1
+  6374 zmedico  tell people that the FILES section is not supposed to be
+                complete (and sneak in a few style fixups) (trunk r6347:6348)
+
+
+man/portage.5
+  6375 zmedico  document /var/cache/edb/, /var/db/pkg/, and
+                /var/lib/portage/config (trunk r6348:6349)
+
+
+pym/portage.py
+  6326 zmedico  Fix missing import. (trunk r6324:6325)
+  6355 zmedico  Only apply permissions to ccache, confcache, and distcc dirs
+                when they are created in order to avoid interference with
+                whatever the user's preferred permissions are. Thanks to
+                Diego Petten?\195?\178 <flameeyes@gmail.com> for reporting.
+                (trunk r6353:6354)
+  6359 zmedico  Don't load FEATURES in load_infodir() because FEATURES from
+                the build host shouldn't be interpreted asFEATURES on the
+                client system. Thanks to Thanks to Chri
+  6361 zmedico  Efficiently recycle partial valid vdb cache when possible.
+                This reduces disk load when switching between versions of
+                portage that cache different keys. (trunk r6359:6360)
+  6385 zmedico  Use catpkgsplit instead of pkgsplit for consistency with
+                usage elsewhere. (trunk r6383:6384)
+  6387 zmedico  Add CATEGORY to blacklisted variables since it can interfere
+                with CATEGORY guessing inside doebuild. (trunk r6385:6386)
+
+
+pym/portage_checksum.py
+  6333 zmedico  For bug #173184, handle the CommandNotFound that is produced
+                during uninstallation of prelink. (trunk r6331:6332)
+
+
+=============================================================================
+2.1.2.3
+2007-03-29
+branches/2.1.2 revision 6322
+=============================================================================
+
+
+bin/doman
+  6272 zmedico  For bug #172033, remove the obsolete QA Notice for man pages
+                that are already compressed. (trunk r6270:6271)
+
+
+bin/ebuild.sh
+  6213 zmedico  For bug #163262 and conformance with section 7.2 of the PMS,
+                make the export attribute of variables persist between ebuild
+                phases. (trunk r6211:6212)
+  6298 zmedico  source ${T}/environment before the definition of qa_source()
+                and qa_call() so that the call stack shows the original files
+                and line numbers instead of those from ${T}/environment.
+                Thanks to Markus Ullmann <jokey@gentoo.org> for reporting.
+                (trunk r6296:6297)
+  6300 zmedico  Filter the readonly attribute from variables saved in
+                ${T}/environment to prevent 'readonly variable' error
+                messages in later phases. (trunk r6298:6299)
+  6302 zmedico  Properly anchor sed regexp for readlonly attribut filtering.
+                (trunk r6300:6301)
+
+
+bin/ecompress
+  6294 zmedico  send stdout to /dev/null since we rely on the output of
+                stdout here to determine the proper suffix #171212 (trunk
+                r6228:6229)
+  6295 zmedico  drop the need for the force flag by default and just delete
+                the existing files automatically #171007 (trunk r6218:6219)
+
+
+bin/ecompressdir
+  6296 zmedico  forcibly break all hard links so we dont need to rely on
+                --force in compressor (trunk r6220:6221)
+  6310 zmedico  For bug #172539, fix ecompressdir suffix handling so that
+                automatic decompression of Z, gz, and bz2 suffixes works
+                properly. (trunk r6308:6309)
+
+
+bin/emerge
+  6274 zmedico  Allow the merge task to continue despite conflicts when
+                --fetch-all-uri is specified. (trunk r6272:6273)
+  6276 zmedico  return from the merge task instead of calling sys.exit
+                directly. (trunk r6274:6275)
+  6278 zmedico  Verify all ebuild manifests before building anything now so
+                that the user is notified of failure as soon as possible.
+                (trunk r6276:6277)
+  6284 zmedico  Verify the Manifest first even if there's only one package
+                (prior to the fetch phase). (trunk r6282:6283)
+  6306 zmedico  Convert "ebuild" and "binary" "nomerge" nodes into
+                "installed" nodes for greater consistency in the depgraph.
+                (trunk r6304:6305)
+  6308 zmedico  Correctly pull the metadata again when the node is converted.
+                (trunk r6306:6307)
+  6322 zmedico  For bug #172571, use socket.AF_INET as the default family for
+                socket.getaddrinfo(). (trunk r6320:6321)
+
+
+bin/emerge-webrsync
+bin/etc-update
+pym/portage_locks.py
+  6293 zmedico  For bug #170178, remove all hardcoded references to
+                '/usr/lib/portage'. (trunk r6202:6203)
+
+
+bin/prepinfo
+  6206 zmedico  Make prepinfo remove installed info indexes recursively.
+                Thanks to Christian Faulhammer <opfer@gentoo.org> for
+                reporting (see bugs #162675 and #170133). (trunk r6204:6205)
+
+
+man/make.conf.5
+  6304 zmedico  Synchronize PORTAGE_COMPRESS_FLAGS to reflect that -9 is the
+                default now. (trunk r6302:6303)
+
+
+pym/cache/flat_hash.py
+  6266 zmedico  Ignore non-existent directories for bug #171809. This is
+                required for readonly mode. (trunk r6264:6265)
+
+
+pym/portage.py
+  6214 zmedico  Automatically convert ROOT and PORTAGE_CONFIGROOT to absolute
+                paths when necessary since relative paths lead to problems.
+                (trunk r6209:6211)
+  6216 zmedico  For bug #171117, ensure that the new and old config have
+                different timestamps (for the benefit of programs like rsync
+                that need distiguishable timestamps to detect file changes).
+                Thanks to Ben Bennett <sink@limey.net> for reporting. (trunk
+                r6214:6215)
+  6218 zmedico  Fix a utime call to prevent a timestamp collision for bug
+                #171117. (trunk r6216:6217)
+  6268 zmedico  For bug #171840, consider all choices for slot intersection
+                and promote those that have upgrades relative to other
+                choices. (trunk r6266:6267)
+  6270 zmedico  Clean up and simplify preference selection logic for bug
+                #171840. (trunk r6268:6269)
+  6293 zmedico  For bug #170178, remove all hardcoded references to
+                '/usr/lib/portage'. (trunk r6202:6203)
+
+
+=============================================================================
+2.1.2.2
+2007-03-07
+branches/2.1.2 revision 6187
+=============================================================================
+
+
+bin/ecompress
+bin/ecompressdir
+  6177 zmedico  allow people to disable compression by setting the
+                PORTAGE_COMPRESS variables to "" (trunk r6173:6174)
+
+
+bin/emerge
+  6170 zmedico  Display blockers at the end of the list so that it will more
+                often be easy for the user to see them in a terminal. Thanks
+                to iapitus and hydrogen for the suggestion. (trunk
+                r6168:6169)
+  6176 zmedico  Avoid pointless population of the binary tree when --buildpkg
+                is enabled. Thanks to vapier for reporting. (trunk
+                r6174:6175)
+  6187 zmedico  For bug #169620, in --tree display always show the dowload
+                size on the node that is "ordered" rather than one of it's
+                "nomerge" counterparts. (trunk r6185:6186)
+
+
+=============================================================================
+2.1.2.1
+2007-03-03
+branches/2.1.2 revision 6167
+=============================================================================
+
+
+bin/emerge
+  6159 zmedico  Only prune duplicate consecutive nodes if they both have
+                depth == 0. (trunk r6157:6158)
+  6161 zmedico  For bug #169187, make --depclean prune unneeded slots such
+                that it is consistent with the world update algorithm. (trunk
+                r6159:6160)
+  6163 zmedico  Add a note about --with-bdeps in the --depclean failure
+                message. (trunk r6161:6162)
+  6165 zmedico  Fix the minimum index for pruning consecutive duplicate
+                nodes. (trunk r6163:6164)
+
+
+pym/portage.py
+  6167 zmedico  Remove the KVERS environment variable since it's code that
+                creates it is broken anyway (only sets KVERS="." in the
+                general case). (trunk r6165:6166)
+
+
+pym/portage_locks.py
+  6157 zmedico  Pass waiting_msg into recursive lockfile() calls. (trunk
+                r6155:6156)
+
+
+=============================================================================
+2.1.2-r14
+2007-03-03
+branches/2.1.2 revision 6149
+=============================================================================
+
+
+bin/emerge
+  6134 zmedico  When emerge automatically resumes, add --ignore-default-opts
+                to the command line in order to prevent things like --ask
+                from leaking in via EMERGE_DEFAULT_OPTS. Thanks to Peter
+                Weller <welp@gentoo.org> for reporting. (trunk r6132:6133)
+  6136 zmedico  For bug #169046, fill in the --tree display with "nomerge"
+                nodes so that the user can always see at lease 1 parent on
+                any non-root node. Packages may appear in the display list
+                multiple times, and will be marked "nomerge" when their
+                position in the list does not correspond to actual merge
+                order. (trunk r6134:6135)
+  6142 zmedico  s/node/selected_parent/ for clarity (trunk r6140:6141)
+  6149 zmedico  Make sure that excess "nomerge" nodes are pruned correctly.
+                (trunk r6147:6148)
+
+
+man/emerge.1
+  6139 zmedico  update --help example to match current behavior #168678 by
+                Arthur Hagen (trunk r6099:6100)
+
+
+pym/portage.py
+  6140 zmedico  Fix types.InstanceType test which is failing now for some
+                reason. (trunk r6136:6137)
+  6144 zmedico  For bug #138840, show a more informative message when waiting
+                for a distfiles lock due to parallel-fetch. Thanks to David
+                Watzke <david@watzke.cz> for the initial patch. (trunk
+                r6142:6143)
+
+
+pym/portage_data.py
+  6147 zmedico  Add missing sys import. (trunk r6145:6146)
+
+
+pym/portage_locks.py
+  6144 zmedico  For bug #138840, show a more informative message when waiting
+                for a distfiles lock due to parallel-fetch. Thanks to David
+                Watzke <david@watzke.cz> for the initial patch. (trunk
+                r6142:6143)
+
+
+=============================================================================
+2.1.2-r13
+2007-03-01
+branches/2.1.2 revision 6130
+=============================================================================
+
+
+bin/emerge
+  6105 zmedico  For bug #168646, don't bail out immediately when rsync
+                detects protocol incompatibility (code 2) during fetching of
+                the timestamp file. Retry for a better server (up to
+                PORTAGE_RSYNC_RETRIES). (trunk r6103:6104)
+  6110 zmedico  Use an alarm signal to implement a timeout when rsync is
+                fetching the server timestamp file, since rsync's --timeout
+                option doesn't apply to the initial connection attempt.
+                (trunk r6108:6109)
+  6112 zmedico  Make sure pids are appropriately removed from
+                portage_exec.spawned_pids. (trunk r6110:6111)
+  6114 zmedico  Merge --quiet fixes from trunk r6112:6113
+  6118 zmedico  For consistency, remove exit code 2 (protocol
+                incompatibility) from the other list of rsync exit codes.
+                (trunk r6116:6117)
+  6120 zmedico  Fix broken except statement syntax. (trunk r6118:6119)
+  6122 zmedico  Fix the rest of the broken except statement syntax. (trunk
+                r6120:6121)
+  6124 zmedico  Fix broken rsync exitcode shift. (trunk r6122:6123)
+  6126 zmedico  Remove unnecessary print statement reported by solar. (trunk
+                r6124:6125)
+  6128 zmedico  Even if there's no timestamp available locally, fetch the
+                timestamp anyway as an initial probe to verify that the
+                server is responsive. This protects us from hanging
+                indefinitely on a connection attempt to an unresponsive
+                server which rsync's --timeout option does not prevent.
+                (trunk r6126:6127)
+  6130 zmedico  For bug #168646, remove --prune-empty-dirs from
+                PORTAGE_RSYNC_OPTS since it's only a small optimization and
+                it's inconvenient to force >=rsync-2.6.4 on server admins at
+                this time. If users desire, they can still add it to
+                PORTAGE_RSYNC_EXTRA_OPTS. (trunk r6128:6129)
+
+
+bin/etc-update
+  6116 zmedico  Add compatibility code to avoid the GNU specific --reference
+                option of chmod. Thanks to Timothy Redaelli
+                <drizzt@gentoo.org>. (trunk r6114:6115)
+
+
+cnf/make.globals
+  6130 zmedico  For bug #168646, remove --prune-empty-dirs from
+                PORTAGE_RSYNC_OPTS since it's only a small optimization and
+                it's inconvenient to force >=rsync-2.6.4 on server admins at
+                this time. If users desire, they can still add it to
+                PORTAGE_RSYNC_EXTRA_OPTS. (trunk r6128:6129)
+
+
+pym/cache/fs_template.py
+  6122 zmedico  Fix the rest of the broken except statement syntax. (trunk
+                r6120:6121)
+
+
+pym/portage.py
+  6103 zmedico  For bug #168823, fix broken except statement syntax that
+                prevents the ValueError from being caught as intended. (trunk
+                r6101:6102)
+
+
+=============================================================================
+2.1.2-r12
+2007-02-26
+branches/2.1.2 revision 6089
+=============================================================================
+
+
+bin/ecompress
+man/make.conf.5
+  6089 zmedico  For bug #168267, use add --force to the default
+                PORTAGE_COMPRESS_FLAGS so that hardlinks are automatically
+                broken. (trunk r6087:6088)
+
+
+bin/ecompressdir
+  6087 zmedico  For compatibility with older findutils, don't use the -L
+                predicate (bug #168432). (trunk r6085:6086)
+
+
+bin/emerge
+cnf/make.globals
+  6071 zmedico  For bug #167668, prune empty ${FILESDIR}s by adding
+                --prune-empty-dirs to PORTAGE_RSYNC_OPTS. Thanks to Ulrich
+                Mueller <ulm@kph.uni-mainz.de> for the suggestion. (trunk
+                r6069:6070)
+
+
+pym/portage.py
+  6069 zmedico  Clean up os.environ["USERLAND"] pollution from the
+                portage_data module so that it doesn't interfere with
+                repoman. (trunk r6067:6068)
+
+
+=============================================================================
+2.1.2-r11
+2007-02-23
+branches/2.1.2 revision 6067
+=============================================================================
+
+
+bin/emerge
+  6018 zmedico  As requested by vapier, don't show the merge list in --quiet
+                mode unless it's explicitly requested via --ask or --pretend.
+                (trunk r6016:6017)
+  6049 zmedico  For bug #167668, use an rsync "hide" filter rule to exclude
+                **/files/digest-* and delete them on the receiver. (trunk
+                r6046:6047)
+  6050 zmedico  Remove quotes since rsync doesn't accept them (and there is
+                no shell to remove them since we use spawn() for rsync now).
+                (trunk r6047:6048)
+  6052 zmedico  spawn rsync without a shell. (trunk r6050:6051)
+  6059 zmedico  Do not show the spinner and the "Calculating dependencies"
+                message for installation actions when the --nodeps option has
+                been specified. Thanks to David Watzke <david@watzke.cz> for
+                this patch from bug #168169. (trunk r6057:6058)
+  6063 zmedico  As requested by solar, never show a merge list unless it's
+                explicitly requested by --ask, --pretend, or --tree.
+  6065 zmedico  As requested by solar, never show a merge list unless it's
+                explicitly requested by --ask, --pretend, or --tree. (trunk
+                r6064)
+  6067 zmedico  Allow --verbose to trigger a merge list even without
+                --pretend, --ask, or --tree. Thanks to agaffney and zlin for
+                the suggestion. (trunk r6065:6066)
+
+
+bin/prepstrip
+  6061 zmedico  Filter paths matching '/<built-in>$' that come from
+                debugedit. Thanks to Ed Catmur for this patch from bug
+                #165342.
+
+
+bin/repoman
+  6025 zmedico  s/x/xs/ to fix a typo in a variable name. (trunk r6022:6023)
+  6026 zmedico  For consistency, replace multiple os.getcwd() calls with the
+                "mydir" variable. (trunk r6023:6024)
+  6028 zmedico  Fix stardir and repodir logic from the previous commit.
+                (trunk r6026:6027)
+  6030 zmedico  Avoid a TypeError when commitmessagefile is None. (trunk
+                r6028:6029)
+  6032 zmedico  Use startdir instead of mydir since mydir has a trailing
+                slash which triggers normalization issues with the dirname
+                function. (trunk r6030:6031)
+  6034 zmedico  Fix more broken commitmessagefile handling. (trunk
+                r6032:6033)
+  6037 zmedico  Fix broken file list handling for FEATUES=sign when only the
+                Manifest has changed. Add some sanity checks for file list
+                handling when repolevel < 3. (trunk r6034:6036)
+  6044 zmedico  For bug #167667, add support for
+                ${PORTDIR}/manifest1_obsolete and automatically remove
+                ${FILESDIR}/digest-* from cvs when appropriate. (trunk
+                r6041:6042)
+
+
+cnf/make.globals
+  6049 zmedico  For bug #167668, use an rsync "hide" filter rule to exclude
+                **/files/digest-* and delete them on the receiver. (trunk
+                r6046:6047)
+
+
+pym/portage.py
+  6020 zmedico  For bug #167795, try avoid the population routine when
+                possible, so that FEATURES=buildpkg doesn't always force
+                population. (trunk r6018:6019)
+  6040 zmedico  Make sure that ${A} in initialized in case pkg_nofetch()
+                needs to be called. Thanks to Peper for reporting. (trunk
+                r6038:6039)
+  6043 zmedico  For bug #167667, use the existence of
+                ${PORTDIR}/manifest1_obsolete to trigger the disabling of
+                manifest1/digest file generation. This toggle is repo/overlay
+                specific, allowing a specific overlay to drop manifest1 by
+                adding the manifest1_obsolete file. (trunk r6040:6041)
+  6057 zmedico  Make verify_all() return an "insufficient data" error if
+                there is not at least one supported hash type. Make fetch()
+                bail out when this error occurs. (trunk r6054:6056)
+
+
+pym/portage_checksum.py
+  6057 zmedico  Make verify_all() return an "insufficient data" error if
+                there is not at least one supported hash type. Make fetch()
+                bail out when this error occurs. (trunk r6054:6056)
+
+
+pym/portage_exec.py
+  6022 zmedico  Raise a CommandNotFound exception when necessary, to ease
+                troubleshooting. Thanks to marienz for reporting. (trunk
+                r6020:6021)
+
+
+pym/portage_manifest.py
+  6043 zmedico  For bug #167667, use the existence of
+                ${PORTDIR}/manifest1_obsolete to trigger the disabling of
+                manifest1/digest file generation. This toggle is repo/overlay
+                specific, allowing a specific overlay to drop manifest1 by
+                adding the manifest1_obsolete file. (trunk r6040:6041)
+  6046 zmedico  Don't bother to parse ${FILESDIR}/digest-* when
+                manifest1_compat is disabled. (trunk r6044:6045)
+
+
+=============================================================================
+2.1.2-r10
+2007-02-19
+branches/2.1.2 revision 6016
+=============================================================================
+
+
+bin/archive-conf
+bin/chkcontents
+bin/clean_locks
+bin/dispatch-conf
+bin/ebuild
+bin/env-update
+bin/fix-db.py
+bin/fixpackages
+bin/md5check.py
+bin/pkgname
+bin/portageq
+bin/regenworld
+bin/repoman
+bin/xpak
+  6016 zmedico  For bug #167217, don't hardcode /usr/lib/portage. (trunk
+                r5945)
+
+
+bin/ebuild.sh
+  6003 zmedico  When calling tar, always exclud . in order to preserver
+                PORTAGE_WORKDIR_MODE. Thanks to Brian Harring in bug #167544.
+                (trunk r6001:6002)
+  6005 zmedico  Don't exclude . since that excludes the entire contents of
+                some tar files. (trunk r6003:6004)
+
+
+bin/emaint
+  5987 zmedico  For bug #166785, check for invalid categories in the world
+                file. (trunk r5985:5986)
+  6016 zmedico  For bug #167217, don't hardcode /usr/lib/portage. (trunk
+                r5945)
+
+
+bin/emerge
+  5957 zmedico  In the event of a circular dependency panic, eliminate root
+                nodes in order to reduce the noise level to a minimum. (trunk
+                r5956)
+  5966 zmedico  For bug #158100, use an exact reversal of the actual merge
+                order for --tree output. It's more efficient than doing 2
+                order calculations. (trunk r5965)
+  5968 zmedico  Optimize merge order calculation for --tree output when
+                necessary. (trunk r5967)
+  5985 zmedico  For bug #166939, make --nodeps work like a normal package for
+                new-style virtuals. (trunk r5981:5982 and r5983:5984)
+  5997 zmedico  For bug #167450, optimize merge order by delaying the merge
+                of root nodes. (trunk r5995:5996)
+  5999 zmedico  For bug #166880, always display the merge list (allowing
+                --tree to be obeyed in any case). (trunk r5997:5998)
+  6001 zmedico  For bug #166880, always display the merge list header. (trunk
+                r5999:6000)
+  6007 zmedico  For bug #166564, make a circular dependency panic more user
+                friendly by displaying the USE flags that are enabled on
+                nodes that are part of dependency cycles and display a note
+                hinting that circular dependencies can often be avoided by
+                temporarily disabling USE flags. (trunk r6005:6006)
+  6009 zmedico  Automatically enable --tree mode when displaying nodes with
+                circular deps. (trunk r6007:6008)
+  6011 zmedico  For bug #167450, optimize leaf node selection by ordering
+                nodes from highest to lowest overall reference count. (trunk
+                r6009:6010)
+  6013 zmedico  Make digraph._merge_order_bias() operate on a single digraph
+                that's passed in. (trunk r6011:6012)
+  6015 zmedico  Optimize order for --tree display of circular dependencies.
+                (trunk r6013:6014)
+  6016 zmedico  For bug #167217, don't hardcode /usr/lib/portage. (trunk
+                r5945)
+
+
+bin/etc-update
+  5971 zmedico  Fix CONFIG_PROTECT_MASK support. Thanks to piavlo
+                <piavka@cs.bgu.ac.il> for this patch from bug #166837. (trunk
+                r5968:5970)
+
+
+pym/output.py
+  5958 zmedico  Make xterm titles work even when color is disabled. Thanks to
+                Joachim Kaeber <joachim.kaeber@web.de> in bug #166255. (trunk
+                r5949:5950)
+
+
+pym/portage.py
+  5972 zmedico  Detect potential issues with mtime granlarity in env_update()
+                and sleep if necessary. Thanks to Brian Harring for
+                reporting. (trunk r5960:5961)
+  5989 zmedico  For bug #163990, warn about ebuilds with invalid categories
+                and do not allow them to be installed. (trunk r5987:5988)
+  5991 zmedico  For bug #163990, warn about binary packages with invalid
+                categories and do not allow them to be installed. (trunk
+                r5989:5990)
+
+
+=============================================================================
+2.1.2-r9
+2007-02-07
+branches/2.1.2 revision 5929
+=============================================================================
+
+
+bin/dispatch-conf
+  5915 zmedico  For bug #165780, make config-protect code consistently ignore
+                '.*~' and '.*.bak'. (trunk r5914)
+
+
+bin/ebuild
+pym/portage_dep.py
+  5911 zmedico  For backward compatibility with api consumers,
+                _dep_check_strict behavior will be explicitly enabled as
+                necessary. Thanks to Brian <dol-sen@telus.net> for reporting
+                issues with porthole and equery. (trunk r5907)
+
+
+bin/ebuild.sh
+  5913 zmedico  Only echo PORTAGE_LOG_FILE if it's actually set (may not be
+                if sesandbox is enabled). (trunk r5912)
+
+
+bin/emerge
+  5909 zmedico  For bug #165783, handle an InvalidDependString exception
+                triggered by an invalid SRC_URI. (trunk r5908)
+  5911 zmedico  For backward compatibility with api consumers,
+                _dep_check_strict behavior will be explicitly enabled as
+                necessary. Thanks to Brian <dol-sen@telus.net> for reporting
+                issues with porthole and equery. (trunk r5907)
+  5915 zmedico  For bug #165780, make config-protect code consistently ignore
+                '.*~' and '.*.bak'. (trunk r5914)
+
+
+bin/repoman
+  5919 zmedico  Enable strict dep checking for repoman. (trunk r5918)
+  5923 zmedico  For bug #165783, handle a potential InvalidDependString
+                exception in repoman and report a SRC_URI.syntax failure.
+                (trunk r5922)
+  5929 zmedico  Make the "lfull" output more succinct by omitting categories
+                for which there are no violations. (trunk r5928)
+
+
+pym/portage.py
+  5917 zmedico  For bug #165783, handle a potential InvalidDependString
+                exception inside digestgen(). (trunk r5916)
+  5921 zmedico  For bug #165783, handle a potential InvalidDependString
+                exception inside doebuild(). (trunk r5920)
+  5925 zmedico  Synchronize required hash code in all relevant places. (trunk
+                r5924)
+
+
+pym/portage_const.py
+pym/portage_manifest.py
+  5925 zmedico  Synchronize required hash code in all relevant places. (trunk
+                r5924)
+
+
+tests/portage_dep/test_isvalidatom.py
+  5927 zmedico  Turn on strict dep checking to fix the isvalidatom test
+                (trunk r5926).
+
+
+=============================================================================
+2.1.2-r8
+2007-02-05
+branches/2.1.2 revision 5901
+=============================================================================
+
+
+bin/emerge
+  5898 zmedico  For bug #165382, show a helpful message if an exception is
+                raised from cpv_expand(). (trunk r5897)
+
+
+bin/repoman
+  5900 zmedico  For bug #165349, use the portage_versions regex (via
+                pkgsplit) instead of the incompatible ones that repoman
+                currently uses. (trunk r5887:5888)
+
+
+man/emerge.1
+  5899 zmedico  Document --config-root for bug #165334. (trunk r5888:5889)
+
+
+pym/portage.py
+  5896 zmedico  For bug #165382, don't raise a ValueError in cpv_expand() if
+                there are only two matches and one of them is a virtual.
+                Prefer the non-virtual instead. (trunk r5889:5891)
+  5901 zmedico  Ensure that the code for bug #165382 only affects name
+                collisions with virtuals. (trunk r5890:5891)
+
+
+=============================================================================
+2.1.2-r7
+2007-02-03
+branches/2.1.2 revision 5884
+=============================================================================
+
+
+bin/ebuild.sh
+  5882 zmedico  For bug #165034, make sure that symlinks are excluded from
+                chmod calls. (trunk r5876:5879)
+
+
+man/make.conf.5
+  5884 zmedico  add warning about storing data in PORTDIR (trunk r5865:5866)
+
+
+pym/cache/util.py
+  5881 zmedico  In order to correctly handl the case of target caches that
+                don't have complete eclass entries, validate the set of
+                interited eclasses to make sure it is correct (since
+                timestamp validation is not applicable). (trunk r5880)
+
+
+pym/portage.py
+  5883 zmedico  For bug #165065, use the proper RESTRICT setting when
+                fetching files in digestgen(). (trunk r5874:5875)
+
+
+=============================================================================
+2.1.2-r6
+2007-02-01
+branches/2.1.2 revision 5869
+=============================================================================
+
+
+bin/ebuild.sh
+  5843 zmedico  For bug #164617, don't change permissions on ${WORKDIR} with
+                unpack(). (trunk r5842)
+  5846 zmedico  Use find + xargs to avoid a potential 'Argument list too
+                long' from bash. (trunk r5844:5845)
+
+
+bin/emerge
+  5844 zmedico  For bug #164363, shuffle the ip addresses returned from
+                socket.getaddrinfo(). (trunk r5832:5833)
+  5860 zmedico  Fix --newuse so that it works correctly with --usepkg. (trunk
+                r5859)
+  5867 zmedico  Rename dir.bz2 since that's the most likely case now. (trunk
+                r5864:5865)
+  5868 zmedico  Load the most current variables from /etc/profile.env for
+                post_emerge stuff. (trunk 5857:5858)
+
+
+bin/emerge-webrsync
+  5841 zmedico  For bug #164532, don't rely on ${USERLAND} since the portage
+                tree might be empty. (trunk r5840)
+
+
+pym/portage.py
+  5869 zmedico  Don't use os.path.isdir() because it can swallow errors
+                related to filesystem/disk corruption. (trunk r5851:5852)
+
+
+=============================================================================
+2.1.2-r5
+2007-01-28
+branches/2.1.2 revision 5830
+=============================================================================
+
+
+bin/check-implicit-pointer-usage.py
+  5823 zmedico  translate unicode quotes to ascii ones so we can keep our
+                regex simple (trunk r5795:5796 and r5803:5804)
+
+
+bin/ecompressdir
+  5826 zmedico  add support for transparently decompressing gz/Z/bz2 files
+                since some upstream packages will compress for us (trunk
+                r5824:5825)
+
+
+bin/emerge
+  5824 zmedico  Remove a stray print statement. Thanks to Rick Warner in bug
+                #125261. (trunk r5798:5799)
+  5828 zmedico  For bug #164078, don't trigger the CLEAN_DELAY countdown for
+                autoclean operations since those are most likely unattended.
+                Thanks to Dan <hydrogen@notyetimplemented.com> for the
+                initial patch. (trunk r5827)
+  5830 zmedico  Ignore EEXIST from rmdir since some kernels (such as solaris)
+                return that instead of ENOTEMPTY. (trunk r5798)
+
+
+bin/env-update
+  5829 zmedico  Catch EACCESS when running env-update, orignal patch by
+                <phajdan.jr@gmail.com> (bug #106061) (trunk r5802:5803 and
+                r5813:5814)
+
+
+bin/repoman
+  5822 zmedico  Can't delete variable that doesn't exist anymore (bug
+                #164280) (trunk r5816:5817 and r5820:5821)
+
+
+pym/portage.py
+  5830 zmedico  Ignore EEXIST from rmdir since some kernels (such as solaris)
+                return that instead of ENOTEMPTY. (trunk r5798)
+
+
+=============================================================================
+2.1.2-r4
+2007-01-24
+branches/2.1.2 revision 5771
+=============================================================================
+
+
+bin/repoman
+  5771 zmedico  demote KEYWORDS.missing to a warning to make KEYWORDS=''
+                valid (trunk r5767:5768)
+
+
+pym/portage.py
+  5770 zmedico  Fix broken line number counting for CONTENTS. (trunk
+                r5764:5765)
+
+
+=============================================================================
+2.1.2-r3
+2007-01-23
+branches/2.1.2 revision 5764
+=============================================================================
+
+
+NEWS
+man/portage.5
+  5762 zmedico  Add new ** for package.keywords token to bypass keyword
+                visibility layer (trunk r5758:5760)
+
+
+pym/portage.py
+  5761 zmedico  For bug #163219, handle binpkgs that have missing PF
+                metadata. (trunk r5756:5757)
+  5762 zmedico  Add new ** for package.keywords token to bypass keyword
+                visibility layer (trunk r5758:5760)
+  5764 zmedico  For bug #142279, detect and warn about null bytes in
+                CONTENTS. (trunk r5762:5763)
+
+
+=============================================================================
+2.1.2-r2
+2007-01-21
+branches/2.1.2 revision 5750
+=============================================================================
+
+
+bin/ecompressdir
+  5740 zmedico  Use XARGS for portable xargs handling when find doesn't find
+                any files.
+
+
+bin/emerge
+  5738 zmedico  For bug #161356, fix error handling for currupt ebuilds.
+                (trunk 5735:5737)
+
+
+man/emerge.1
+  5744 zmedico  Minor fixes thanks to Fabio Correa <facorread@alexandria.cc>
+                in bug #162647. (trunk r5741:5742)
+
+
+pym/portage.py
+  5738 zmedico  For bug #161356, fix error handling for currupt ebuilds.
+                (trunk 5735:5737)
+  5745 zmedico  Don't require MANIFEST2 hashes since that can trigger
+                excessive fetches when sufficient digests already exist.
+                Thanks to vapier for reporting. (trunk r5742:5743)
+  5747 zmedico  To ease transition while Manifest 1 is being removed, only
+                require hashes that will exist before and after the
+                transition. (trunk r5746)
+  5750 zmedico  For bug #163083, handle an UnsupportedAPIException thrown
+                from the prerm phase. (trunk r5748:5749)
+
+
+pym/portage_exception.py
+  5750 zmedico  For bug #163083, handle an UnsupportedAPIException thrown
+                from the prerm phase. (trunk r5748:5749)
+
+
+=============================================================================
+2.1.2-r1
+2007-01-18
+branches/2.1.2 revision 5720
+=============================================================================
+
+
+bin/ebuild.sh
+  5688 zmedico  Use the portable -o option for tar. Thanks to Timothy
+                Redaelli <drizzt@gentoo.org> for the patch. (trunk r5676)
+
+
+bin/ecompressdir
+  5681 zmedico  make sure we rename links and not just what they point to
+                #162451 (trunk r5677:5678)
+
+
+bin/emerge
+  5717 zmedico  Simplify rsync timestamp.chk handling and print the correct
+                path for bug #50738. Thanks to jeka for reporting on irc.
+                (trunk r5716)
+  5720 zmedico  dump emerge's normpath in favor of portage_util's
+                normalize_path (trunk r5698)
+
+
+bin/misc-functions.sh
+  5696 zmedico  arm and superh support exec stack stuff now (trunk
+                r5693:5695)
+
+
+bin/repoman
+  5687 zmedico  Merge repoman fixes from trunk r5660:5661 and r5665:5669.
+
+
+pym/portage.py
+  5683 zmedico  Make dep_check() work correctly with --usepkgonly. This
+                solves issues reported by Brent Baude <ranger@gentoo.org>
+                (trunk r5674, 5675, 5678, and 5682)
+  5685 zmedico  Fix elimination of duplicate virtuals between the binpkg repo
+                and installed packages. (trunk r5684)
+  5686 zmedico  Merge doebuild *DEPEND validation from trunk r5652:5655.
+  5692 zmedico  For bug #162404, spawn tee outside the sesandbox domain so
+                that it reads from a pipe between two domains. (trunk
+                r5689:5691)
+  5715 zmedico  Validate ebuild names in portdbapi.cp_list() and raise an
+                raise an informative InvalidData exception from
+                match_from_list when necessary. (trunk r5712:5714)
+  5719 zmedico  For bug #162404, when sesandbox is enabled, only log if
+                PORT_LOGDIR is explicitly enabled since it is possible that
+                local SELinux security policies do not allow ouput to be
+                piped out of the sesandbox domain. (trunk r5718)
+
+
+pym/portage_dep.py
+  5715 zmedico  Validate ebuild names in portdbapi.cp_list() and raise an
+                raise an informative InvalidData exception from
+                match_from_list when necessary. (trunk r5712:5714)
+
+
+pym/portage_util.py
+  5720 zmedico  dump emerge's normpath in favor of portage_util's
+                normalize_path (trunk r5698)
+
+
+=============================================================================
+2.1.2
+2007-01-14
+trunk revision 5649
+=============================================================================
+
+
+DEVELOPING (Added)
+  5612 antarus  Add a few pretty basic comments on writing code, particularly
+                things that portage used to do (and still does) that are...a
+                bit out of style ;)
+  5633 antarus  fix tabs with patch from Grobian and bug # 161911, fix
+                developing a bit
+
+
+NEWS
+  5367 zmedico  For bug #158931, add some release notes to explain
+                performance penalties for dependency calculations.
+  5481 zmedico  s/prefix/suffix/ Thanks to hydrogen for reporting on irc.
+  5482 zmedico  s/suffix/version prefix/ since it really is a prefix for the
+                version string.
+  5494 genone   Update NEWS with eqawarn and 'ebuild foo test' changes
+  5509 genone   create symlinks to html documentation if DOC_SYMLINK_DIR is
+                set, original patch by TGL <degrenier@easyconnect.fr> (bug
+                #67130)
+  5645 zmedico  For bug #69021, add news about FEATURES="test" implying
+                USE="test".
+
+
+RELEASE-NOTES
+  5367 zmedico  For bug #158931, add some release notes to explain
+                performance penalties for dependency calculations.
+
+
+TEST-NOTES (Added)
+  5531 antarus  add a few tips on adding tests, and kinks in the current
+                system, I hope to fix the import bug soon
+  5539 antarus  edit test-notes
+
+
+bin/archive-conf
+bin/chkcontents
+bin/portageq
+bin/regenworld
+  5597 antarus  More String deprecation
+
+
+bin/check-implicit-pointer-usage.py (Added)
+  5449 vapier   add support for scanning of build logs for common issues
+                #111436
+
+
+bin/dispatch-conf
+  5597 antarus  More String deprecation
+  5601 antarus  fix "" " " bug
+  5605 zmedico  Fix a typo.
+
+
+bin/dodoc
+bin/doinfo
+bin/ecompress (Added)
+bin/prepallinfo
+bin/prepallman
+bin/prepinfo
+  5555 vapier   add support for user-customizable compression #9870
+
+
+bin/dohtml
+  5597 antarus  More String deprecation
+  5642 zmedico  Fix dohtml so that it continues to install files even after
+                some fail. Thanks to brad walker <bradmwalker@cableone.net>
+                in bug #149745.
+
+
+bin/doman
+bin/preplib
+  5507 zmedico  For bug #160075, send all 'QA Notice' messages to eqawarn.
+                Also, modify eqawarn to use vecho and send ouput to stderr.
+
+
+bin/ebuild
+  5487 genone   Always run src_test when calling 'ebuild foo test'
+
+
+bin/ebuild.sh
+  5391 zmedico  Use a SIGTERM signal to support a die call inside of a
+                subshell.
+  5392 zmedico  For bug #148603, when an ebuild dies, print eclasses that are
+                from overlays. Thanks to Alec Warner for the initial patch.
+  5425 zmedico  Punt the abort_unpack() handler since it's pointless anyway.
+  5484 antarus  Implement QA checks that attempt to detect changed shopts and
+                IFS in ebuild/eclass/profile code. Spit a warning if that is
+                the case. I expect this check will eventually reset the
+                shopts and IFS, but in this case it may break things that
+                depend on the current behavior
+  5485 antarus  Antarus sucks at bash, thanks for Genone for reporting this
+                major bug.
+  5487 genone   Always run src_test when calling 'ebuild foo test'
+  5488 genone   Disable qa_source usage until it actually works
+  5489 antarus  Zac pointed out that the retcodes would be wrong if stuff
+                failed...Yeah...
+  5492 antarus  Okies this works locally for me now (and Zac)
+  5504 genone   Misc typo fixes, patch by Benno Schulenberg (bug #157812)
+  5507 zmedico  For bug #160075, send all 'QA Notice' messages to eqawarn.
+                Also, modify eqawarn to use vecho and send ouput to stderr.
+  5590 zmedico  For bug #88485, show the location of the build log whenever a
+                build fails.
+  5632 vapier   make sure people call addread/addwrite/adddeny/addpredict
+                correctly
+  5646 zmedico  Disable the test phase when USE=test is masked (for
+                consistency with the fix for bug #69021).
+
+
+bin/ecompressdir (Added)
+  5555 vapier   add support for user-customizable compression #9870
+  5575 vapier   dont compress files that are already compressed and dont do
+                sanity checking on the link dest as we cant properly verify
+                things like absolute symlinks
+  5576 vapier   use cached suffix value and if it is not valid, lets warn
+
+
+bin/emerge
+  5361 zmedico  Show the "Calculating dependencies .. done!" message with
+                --resume since the spinner now runs inside the depgraph
+                constructor. Thanks to antarus for reporting.
+  5388 zmedico  Prevent the regen action from running in --pretend mode.
+  5389 zmedico  When the user has insufficient access privileges, specify
+                whether superuser access or portage group access is required.
+                When only portage group access is required but the user is
+                not in the portage group, call
+                portage_data.portage_group_warning() to remind people that
+                the portage group is a system administration group.
+  5402 zmedico  Use a pickle to cache vdb metadata. This greatly improves the
+                performance for loading the vdb when the buffer cache is
+                cold.
+  5410 zmedico  Use a pickle to cache blockers for all installed packages so
+                that dep_check doesn't have to be called for every single
+                installed package on every invocation of emerge.
+  5411 zmedico  For bug #159161, make emerge --info show USE_EXPAND flags
+                similar to the way it does in merge list output.
+  5412 zmedico  Add some docs for the blockers cache format.
+  5413 zmedico  For bug #159310, don't show a slot collision notice if there
+                are unresolvable blockers.
+  5415 solar    - keep things quiet when uninstalling
+  5416 zmedico  Send stuff that's not a warning or error to stdout rather
+                than stderr.
+  5420 zmedico  Sort the --info USE flags for bug #159161.
+  5421 zmedico  Be slightly more defensive when loading the vdb/blockers
+                caches.
+  5423 zmedico  Do some small fixes to prevent slot collision nodes from
+                interfering with the depgraph.
+  5424 zmedico  Fix 'TypeError: unpack non-sequence' that occurs if myparent
+                is None.
+  5432 zmedico  Use return values instead of direct sys.exit(123) calls when
+                a merge fails.
+  5456 zmedico  Implement distlocks for --getbinpkg so that it works properly
+                when parallel-fetch is enabled. Thanks to Brent Baude
+                <ranger@gentoo.org> for reporting.
+  5465 zmedico  For bug #160299, make sure that emerge sees a somewhat valid
+                COUNTER even when the counter is missing.
+  5503 zmedico  For bug #160971, rename dir.gz to dir.gz.old when necessary
+                to avoid problems with install-info. Thanks to Ed Catmur
+                <ed@catmur.co.uk> for the initial patch.
+  5534 zmedico  For bug #161422, make slot collisions non-fatal in cases
+                where an invalid depgraph is acceptable (--fetchonly, for
+                example).
+  5535 zmedico  Don't allow slot collision nodes to block other packages
+                since blocker validation is only able to account for one
+                package per slot.
+  5536 zmedico  Rename depgraph._invalid_depgraph_is_acceptable() to
+                _accept_collisions() for a better description.
+  5545 genone   Rename 'Last Sync' to 'Timestamp of tree' to clarify the
+                meaning (bug #150051)
+  5565 zmedico  For bug #50738, inform the user about the location of the
+                timestamp file and that it can be removed to force sync.
+  5580 zmedico  For bug #147512, don't print a cryptic error message when an
+                EnvironmentError occurs. Also, allow the user to get a
+                traceback via --debug.
+  5600 antarus  purge string module from emerge
+  5601 antarus  fix "" " " bug
+  5607 zmedico  Revert accidentally modified joins.
+  5621 zmedico  Send the slot collision notice to stderr and only show
+                minimal output in --quiet mode.
+  5623 zmedico  Send the unmerge failure message to stderr.
+  5624 zmedico  Use end_paragraph(1) instead of add_line_break() so that
+                there is really a blank line.
+  5625 zmedico  For bug #144380, disable color at emerge startup and then
+                enable it only when it's absolutely sure that color should be
+                enabled (after EMERGE_DEFAULT_OPTS has been parsed).
+  5627 zmedico  Obey the silent parameter when parsing options.
+  5629 zmedico  Catch InvalidData exceptions for bad atoms passed as emerge
+                arguments.
+
+
+bin/isolated-functions.sh
+  5490 genone   Add new eqawarn function and QA loglevel to be used for QA
+                messages
+  5507 zmedico  For bug #160075, send all 'QA Notice' messages to eqawarn.
+                Also, modify eqawarn to use vecho and send ouput to stderr.
+  5578 zmedico  Fix ebuild environment color.map support so that it works
+                properly through exec calls (since the color variables can
+                not be directly exported due to env pollution).
+
+
+bin/md5check.py
+  5597 antarus  More String deprecation
+  5606 zmedico  Fix a typo.
+
+
+bin/misc-functions.sh
+  5417 vapier   fixup style
+  5442 vapier   merge all of the QA related checks together
+  5449 vapier   add support for scanning of build logs for common issues
+                #111436
+  5466 zmedico  Fix shell glob logic that leads to false positives. Thanks to
+                Flameeyes for reporting.
+  5467 zmedico  Fix one more potential false glob match.
+  5468 vapier   revert previous changes ... ruby.eclass is wrongly polluting
+                env with nullglob
+  5469 vapier   force C locale for now when parsing gcc log files #160234
+  5507 zmedico  For bug #160075, send all 'QA Notice' messages to eqawarn.
+                Also, modify eqawarn to use vecho and send ouput to stderr.
+  5509 genone   create symlinks to html documentation if DOC_SYMLINK_DIR is
+                set, original patch by TGL <degrenier@easyconnect.fr> (bug
+                #67130)
+  5555 vapier   add support for user-customizable compression #9870
+  5579 vapier   drop lazy bindings check once and for all ... the system ldso
+                should have the logic #71609
+
+
+bin/prepall
+  5418 vapier   detect incorrect absolute symlinks in libdirs
+  5442 vapier   merge all of the QA related checks together
+
+
+bin/prepalldocs
+  5555 vapier   add support for user-customizable compression #9870
+  5628 zmedico  Fix a typo.
+
+
+bin/prepman
+  5507 zmedico  For bug #160075, send all 'QA Notice' messages to eqawarn.
+                Also, modify eqawarn to use vecho and send ouput to stderr.
+  5555 vapier   add support for user-customizable compression #9870
+
+
+bin/prepstrip
+  5408 zmedico  For bug #159252, don't preserve file attributes when copying
+                files for installsources. Thanks to Ed Catmur
+                <ed@catmur.co.uk> for this patch.
+  5507 zmedico  For bug #160075, send all 'QA Notice' messages to eqawarn.
+                Also, modify eqawarn to use vecho and send ouput to stderr.
+
+
+bin/repoman
+  5360 zmedico  Only write repo.stats and repo.fails when the repoman user
+                has write access to /var/cache/edb.
+  5438 zmedico  For bug #159224, use separate xmatch caches for each value of
+                ACCEPT_KEYWORDS.
+  5444 zmedico  Optimize dep_zapdeps to work without a vartree when called by
+                repoman.
+  5463 zmedico  Make repoman use portage.normalize_path instead of
+                os.path.normpath. This might solve an issue with incorrect
+                repolevel detection that was reported by drizzt.
+  5470 zmedico  For bug #160310, allow \ inside `` quotes in order to prevent
+                a false Line continuation ("\") Syntax Error.
+  5471 zmedico  For bug #160310, remove the line continuation syntax check
+                since it's still possible for it to generate false positives.
+  5477 zmedico  Fix the digestentry.unused check so that it works properly
+                when old-style files/digest-* don't exist.
+  5480 zmedico  Don't automatically fix digests in --pretend mode.
+  5603 antarus  purge string module from repoman
+
+
+cnf/make.conf
+  5491 genone   Mention new QA loglevel in make.conf.example
+  5543 genone   Update CCACHE docs, patch by Ryan Hill (bug #156865)
+  5544 genone   Add 'stricter' description, misc typo fixes, patch by Max
+                Lorenz (bug #153755)
+
+
+cnf/make.conf.x86.diff
+  5505 genone   Update x86 CFLAGS section, original patch by Peter Gantner
+                (bug #133402)
+
+
+man/ebuild.5
+  5506 genone   Add elog related variables to make.conf(5) with a pointer to
+                make.conf.example. Add elog() description to ebuild(5) and
+                update einfo() description.
+  5542 genone   Remove RESTRICT=sandbox docs until bug #161045 is resolved
+  5643 zmedico  Document PORTAGE_LOG_FILE, update PORTAGE_TMPDIR path which
+                now includes CATEGORY, and lots of style/syntax fixes. Thanks
+                to Arfrever Frehtes Taifersar Arahesis <FFTA@WP.PL> from bug
+                #161979.
+
+
+man/emerge.1
+  5369 antarus  Manpage fix for bug # 158983, thanks to Fabio Correa for the
+                patch
+  5401 antarus  try to give the emerge manpage a facelift, upgrade clean and
+                prune docs, change 'dependency' to 'atom', other minor fixes
+  5404 zmedico  Update emerge --metadata docs for more clarity.
+  5510 genone   Make env variable example about USE shell independent
+
+
+man/make.conf.5
+  5506 genone   Add elog related variables to make.conf(5) with a pointer to
+                make.conf.example. Add elog() description to ebuild(5) and
+                update einfo() description.
+  5543 genone   Update CCACHE docs, patch by Ryan Hill (bug #156865)
+  5552 genone   Add note that any value enables EPAUSE_IGNORE
+  5626 zmedico  Document PORTAGE_COMPRESS and PORTAGE_COMPRESS_FLAGS.
+  5643 zmedico  Document PORTAGE_LOG_FILE, update PORTAGE_TMPDIR path which
+                now includes CATEGORY, and lots of style/syntax fixes. Thanks
+                to Arfrever Frehtes Taifersar Arahesis <FFTA@WP.PL> from bug
+                #161979.
+  5644 zmedico  For bug #161975, document the fact that GENTOO_MIRRORS
+                supports mounted filesystem mirrors.
+  5648 zmedico  Document DOC_SYMLINKS_DIR.
+  5649 zmedico  Fix alphabetical order.
+
+
+man/portage.5
+  5502 zmedico  For bug #161003, disallow virtuals in package.provided and
+                document it. Thanks to Robin Johnson <robbat2@gentoo.org> for
+                the initial patch.
+
+
+pym/cache/metadata_overlay.py
+  5368 zmedico  For forward compatibility, make metadata_overlay pass any
+                additional positional and keyword parameters into the super
+                constructor.
+
+
+pym/cache/sqlite.py
+  5434 zmedico  For bug #159518, increase the "database is locked" timeout.
+
+
+pym/cache/util.py
+  5483 zmedico  For bug #160893, ignore a KeyError during cache cleansing
+                since that key isn't wanted anyway.
+
+
+pym/cache/volatile.py
+  5394 zmedico  Make _setitem do a deepcopy just in case.
+
+
+pym/cvstree.py
+  5594 antarus  Begin the deprecation of the string module
+
+
+pym/dbapi (Added)
+  5450 genone   Allow - in elog module names
+  5451 genone   undo
+
+
+pym/dbapi/__init__.py (Added)
+pym/dbapi/binpkg.py (Added)
+pym/dbapi/ebuild.py (Added)
+pym/dbapi/fake.py (Added)
+pym/dbapi/vardb.py (Added)
+  5450 genone   Allow - in elog module names
+
+
+pym/eclass_cache.py
+  5583 antarus  Fix broad except statement, should only be KeyError
+
+
+pym/elog_modules/mod_save_summary.py
+  5363 genone   List package in summary logfile
+
+
+pym/elog_modules/mod_syslog.py
+  5490 genone   Add new eqawarn function and QA loglevel to be used for QA
+                messages
+
+
+pym/emergehelp.py
+  5404 zmedico  Update emerge --metadata docs for more clarity.
+  5593 zmedico  Remove a duplicate % character.
+
+
+pym/getbinpkg.py
+  5453 zmedico  Use os._exit instead of sys.exit in a forked child process.
+  5454 zmedico  Make sure stderr is flushed since os._exit doesn't flush
+                stdio buffers.
+  5458 zmedico  When fetching metadata from a binhost, reconnect if the http
+                server closes the connection before sending a valid response.
+                Thanks to ranger for reporting.
+  5459 zmedico  Make sure that myid is defined for the previous commit.
+  5585 antarus  getbinpkg.py fix except: open can be IOERror or OSError and
+                cPickle can throw an unpicklingError
+  5586 antarus  EOFError is also important according to Zac
+  5594 antarus  Begin the deprecation of the string module
+  5598 zmedico  Use startswith and endswith to simplify code.
+  5599 zmedico  Fix typos from the previous commit.
+
+
+pym/portage.py
+  5362 antarus  startime is set up in treewalk, so no need to do it
+                globally...
+  5364 genone   disable display of elapsed time for collision-protect as it's
+                for benchmarking purposes and useless to most people.
+  5365 antarus  More Docstrings in portage.py
+  5366 antarus  move actionmap_deps out of global scope and into doebuild
+                where it is actually used, add docstrings to config class in
+                the meantime.
+  5370 antarus  More code cleanup, packagetree appears to be completely
+                unused, so lets remove it in favor of inheriting from object
+  5371 antarus  Docstrings for doebuild
+  5372 antarus  cptot appears to be unused, punting it along with this
+                commented out function, it appears to be unused as well.
+  5382 zmedico  Clone cached match results before returning them from
+                portdbapi.xmatch(). Thanks to Brian <dol-sen@telus.net> for
+                reporting this issue.
+  5383 zmedico  Make bindbapi.aux_get() selectively cache metadata in order
+                to optimize dep matching (like portdbapi does).
+  5384 zmedico  Make sure that bindbapi makes EAPI correctly default to 0 in
+                all possible cases.
+  5385 antarus  more docstrings..
+  5386 antarus  Docstrings for mergeme...
+  5398 zmedico  Allow dep_check to use the global db for compatibility (fixes
+                python-updater breakage).
+  5402 zmedico  Use a pickle to cache vdb metadata. This greatly improves the
+                performance for loading the vdb when the buffer cache is
+                cold.
+  5403 zmedico  Make portdbapi.flush_cache() consistent with
+                vardbapi.flush_cache().
+  5405 zmedico  Allow the list of keys cached by the vardb to change without
+                forcing a cache version bump.
+  5406 zmedico  Make vartree.getslot() use the dbapi for aux_get caching.
+  5407 zmedico  Make vardbapi.cpv_counter() use aux_get for caching.
+  5409 zmedico  For bug #159295 and python-2.3 compatibility, don't assume
+                that dict.update can use an iterable.
+  5414 zmedico  Do some minor cleanup in the dep_zapdeps downgrade avoidance
+                logic (while working toward a fix for bug #159360).
+  5419 zmedico  For bug #159360, make sure that the highest available
+                new-style virtual is selected even if it has depes that
+                aren't already installed.
+  5421 zmedico  Be slightly more defensive when loading the vdb/blockers
+                caches.
+  5422 zmedico  Improve the logic for bug #159360 to ensure that an actual
+                upgrade is selected without any downgrades.
+  5428 zmedico  For bug #151326, prevent invalid comments from being returned
+                by portage.getmaskingreason().
+  5429 zmedico  Correct the package.mask lookup order in getmaskingreason().
+  5430 zmedico  For bug #141361, use an alarm signal to implement a 1 minute
+                timeout for processing inside an elog module.
+  5431 zmedico  Use a try/finally block to ensure that the alarm will always
+                be cancelled appropriately.
+  5432 zmedico  Use return values instead of direct sys.exit(123) calls when
+                a merge fails.
+  5433 zmedico  Send errors in elog_process() to stderr via writemsg.
+  5437 zmedico  Use slot atom matching to simplify detection of downgrades
+                relative to installed packages.
+  5440 zmedico  For bug #159638, fix the UnboundLocalError in
+                vartree.getprovide().
+  5441 zmedico  Fix the writemsg noiselevel from the previous commit.
+  5443 zmedico  Don't bother to list the contents of directories before they
+                are unmerged since it triggers unnecessary stat calls. Thanks
+                to James Cloos <cloos@jhcloos.com> for reporting.
+  5444 zmedico  Optimize dep_zapdeps to work without a vartree when called by
+                repoman.
+  5448 zmedico  Try to create DISTDIR before disabling fetch due to it's
+                nonexistence. Thanks to astinus for reporting.
+  5449 vapier   add support for scanning of build logs for common issues
+                #111436
+  5450 genone   Allow - in elog module names
+  5452 zmedico  When using the spawn's returnpid parameter, manually remove
+                the returned pids from portage_exec.spawned_pids.
+  5457 zmedico  Export EBUILD_PHASE="" when running misc-function.sh in order
+                to prevent bogus phase values coming from ${T}/environment.
+                Thanks to solar for reporting.
+  5464 zmedico  For python-2.3 compatibility, don't pass an iterable into
+                dict.update().
+  5478 zmedico  Don't swallow an IOError if it is thrown from the aux_get
+                call in portdbapi.getfetchlist().
+  5495 zmedico  Split PORTAGE_ELOG_CLASSES outside the loop for better
+                efficiency.
+  5496 zmedico  Make digestgen() force fetch unless all required digest types
+                are available. Thanks to jokey for reporting on irc.
+  5499 zmedico  For bug #161103, don't skip collision-protect checks in cases
+                where the beginning of the file path matches a symlink but is
+                not acually inside a symlinked directory (check the path
+                against symlink + os.path.sep).
+  5502 zmedico  For bug #161003, disallow virtuals in package.provided and
+                document it. Thanks to Robin Johnson <robbat2@gentoo.org> for
+                the initial patch.
+  5508 genone   make.globals has no business in profiles
+  5509 genone   create symlinks to html documentation if DOC_SYMLINK_DIR is
+                set, original patch by TGL <degrenier@easyconnect.fr> (bug
+                #67130)
+  5511 genone   Always use vercmp for cpv comparisons
+  5512 genone   Stupid me, shouldn't jsut move a part of the patch
+  5551 genone   Make FEATURES=test imply USE=test
+  5554 zmedico  Use dict.get() to prevent a potential (bug unlikely)
+                KeyError.
+  5578 zmedico  Fix ebuild environment color.map support so that it works
+                properly through exec calls (since the color variables can
+                not be directly exported due to env pollution).
+  5580 zmedico  For bug #147512, don't print a cryptic error message when an
+                EnvironmentError occurs. Also, allow the user to get a
+                traceback via --debug.
+  5587 antarus  os.cwd can return OSError (maybe IOError with wrong perms for
+                ./, will test actually), load_mod should be IMportError, nuke
+                a stupid try except around shuffle which used to break years
+                ago with old glibcs, remove try except around what appears to
+                be a regex? and make the try except around the unlink a bit
+                cleaner
+  5588 antarus  FIx a bunch of random Except: statements in portage.py, most
+                of them are IO/OS related
+  5589 zmedico  Return early from finddigest if findname2 found nothing.
+  5592 zmedico  Fix incremental virtuals code for the new stricter
+                catpkgsplit behavior.
+  5604 antarus  purge string from portage.py, fix minor bug in portage_util
+  5608 zmedico  Fix more typos.
+  5620 antarus  remove the last of the string module from portage.py
+  5633 antarus  fix tabs with patch from Grobian and bug # 161911, fix
+                developing a bit
+  5634 zmedico  Fix 'TypeError: not all arguments converted during string
+                formatting'. Thanks to marienz.
+  5635 zmedico  Fix reversed arguments.
+  5647 zmedico  Don't warn about /etc/make.profile not being a symlink if it
+                has a parent file.
+
+
+pym/portage_const.py
+  5486 genone   Make PORTAGE_BASE_PATH dynamic based on __file__
+  5493 antarus  This file apparently uses spaces to line everything up pretty
+                (I have weird tabs set, so spacies are good :P)
+
+
+pym/portage_data.py
+  5387 zmedico  Drop the warning messages for users that aren't in the
+                portage group since tpordbapi now correctly puts the on-disk
+                cache into readonly mode in this case (and allows metadata
+                generation in-memory if necessary).
+  5390 zmedico  Make sure that portage_group_warning() will be shown even in
+                quiet mode.
+  5461 zmedico  As a workaround for bug #147625, spawn `id -g portage` in
+                order to get a list of groups for the portage user without
+                the need to call grp.getgrall().
+  5462 zmedico  Use -G instead of -g (typo from the previous commit).
+
+
+pym/portage_dep.py
+  5511 genone   Always use vercmp for cpv comparisons
+  5512 genone   Stupid me, shouldn't jsut move a part of the patch
+  5513 genone   Attach the problematic data to the exception for debugging
+  5514 genone   Make the =* operator more robust
+  5515 genone   Documenting the loop a bit
+  5516 genone   =* operator sucks
+  5517 genone   also sanitize mycpv for =* handling
+  5518 genone   minor performance improvement
+  5519 genone   I hate this thing
+  5520 zmedico  Minor fixes for the =* operator (I hope we're done now :).
+  5521 zmedico  Use startwith to simplify =* matching.
+  5563 antarus  elaborate a bit on isjustname()
+  5571 antarus  Handle the exception in isvalidatom, change it to use a
+                portage exceptoin, thanks to Zac for pointing this out
+  5581 antarus  Change vercmp to use int() instead of string atoi, catch
+                ValueError in pkgcmp
+  5584 antarus  comment the excepts in a few places
+  5595 antarus  more string deprecation
+  5602 antarus  another annoy space bug
+
+
+pym/portage_exception.py
+  5546 genone   Don't escape strings in PortageException as that breaks
+                newline handling (bug 147785)
+  5553 zmedico  Use isinstance(foo, basestring) so that it can work with
+                unicode strings too.
+
+
+pym/portage_exec.py
+  5455 zmedico  Make sure stderr is flushed since os._exit doesn't flush
+                stdio buffers.
+  5584 antarus  comment the excepts in a few places
+
+
+pym/portage_locks.py
+pym/xpak.py
+  5595 antarus  more string deprecation
+
+
+pym/portage_update.py
+  5591 zmedico  Prevent an InvalidData exception during global updates due to
+                the new stricter catpkgsplit behavior.
+
+
+pym/portage_util.py
+  5548 genone   Extend ignore filter for grablines (bug #144445)
+  5550 genone   continue is only for loops
+  5556 antarus  docs for grabdict
+  5595 antarus  more string deprecation
+  5604 antarus  purge string from portage.py, fix minor bug in portage_util
+  5609 zmedico  Fix another typo.
+
+
+pym/portage_versions.py
+  5568 antarus  Valid categories in catpkgsplit
+  5570 antarus  Fix comments for catpkgsplit
+  5571 antarus  Handle the exception in isvalidatom, change it to use a
+                portage exceptoin, thanks to Zac for pointing this out
+  5572 antarus  learn to spell
+  5573 antarus  SpanKY likes the latin categories
+  5574 zmedico  Use a global to ensure that the valid_category regex is
+                cached.
+  5577 zmedico  Allow catpkgsplit to be less strict for atoms that come from
+                installed packages (for backward compatibility).
+  5581 antarus  Change vercmp to use int() instead of string atoi, catch
+                ValueError in pkgcmp
+  5582 antarus  portage_versions.py, more string.atoi -> int, fix another
+                except: that should be ValueError
+  5584 antarus  comment the excepts in a few places
+  5595 antarus  more string deprecation
+
+
+tests/__init__.py
+  5522 antarus  rework test import code, rename test_vercmp to be more
+                generic, add tests for =* glob matches
+  5525 antarus  Take Genone's suggestion and break the modules up into module
+                oriented fashion. Tests for portage.py go in portage/ and so
+                on and so forth...
+  5532 zmedico  Fix module loading.
+  5537 antarus  Add a bit of path mangling to allow deeper tests
+  5538 antarus  remove bogs test dir, add portage_versions
+  5540 antarus  more test re-arranging as Alec can't read what functions are
+                in what files
+  5541 zmedico  Remove / character from module names.
+
+
+tests/portage (Added)
+tests/portage_util (Added)
+  5525 antarus  Take Genone's suggestion and break the modules up into module
+                oriented fashion. Tests for portage.py go in portage/ and so
+                on and so forth...
+  5613 antarus  ignore py[co] in tests
+
+
+tests/portage/__init__.py (Added)
+tests/portage_util/__init__.py (Added)
+  5525 antarus  Take Genone's suggestion and break the modules up into module
+                oriented fashion. Tests for portage.py go in portage/ and so
+                on and so forth...
+  5596 antarus  set Id on tests
+
+
+tests/portage/test_atoms.py
+  5526 antarus  shift test cases around
+  5528 antarus  rename atoms back to vercmp
+
+
+tests/portage/test_atoms.py (from /main/trunk/tests/test_atoms.py:5524) (Added)
+tests/portage_util/test_util.py (from /main/trunk/tests/test_util.py:5523) (Added)
+  5525 antarus  Take Genone's suggestion and break the modules up into module
+                oriented fashion. Tests for portage.py go in portage/ and so
+                on and so forth...
+
+
+tests/portage/test_match_from_list.py (Added)
+  5527 antarus  shift test cases around
+  5540 antarus  more test re-arranging as Alec can't read what functions are
+                in what files
+
+
+tests/portage/test_vercmp.py (Removed)
+tests/portage_versions/test_vercmp.py (from /main/trunk/tests/portage/test_vercmp.py:5528) (Added)
+  5537 antarus  Add a bit of path mangling to allow deeper tests
+
+
+tests/portage/test_vercmp.py (from /main/trunk/tests/portage/test_atoms.py:5526) (Added)
+  5528 antarus  rename atoms back to vercmp
+
+
+tests/portage_dep (Added)
+  5540 antarus  more test re-arranging as Alec can't read what functions are
+                in what files
+  5613 antarus  ignore py[co] in tests
+
+
+tests/portage_dep/__init__.py
+  5596 antarus  set Id on tests
+
+
+tests/portage_dep/__init__.py (from /main/trunk/tests/portage/__init__.py:5536) (Added)
+tests/portage_dep/test_match_from_list.py (from /main/trunk/tests/portage/test_match_from_list.py:5536) (Added)
+  5540 antarus  more test re-arranging as Alec can't read what functions are
+                in what files
+
+
+tests/portage_dep/test_dep_getcpv.py (Added)
+  5561 antarus  I owed brian harring 3.50, for th previous advice about
+                assertEqual/NotEqual, oh, add dep_getcpv tests too
+  5566 antarus  add some invalid ops to getcpv to make sure it returns the
+                cpv still
+  5596 antarus  set Id on tests
+  5633 antarus  fix tabs with patch from Grobian and bug # 161911, fix
+                developing a bit
+
+
+tests/portage_dep/test_dep_getslot.py (Added)
+  5562 antarus  getslot tests
+  5596 antarus  set Id on tests
+  5633 antarus  fix tabs with patch from Grobian and bug # 161911, fix
+                developing a bit
+
+
+tests/portage_dep/test_get_operator.py (Added)
+  5558 antarus  get_operator tests
+  5559 antarus  add some invalid operators to the test to denote that
+                get_operator doesn't validate them, also make sure some
+                common mis-typed things are tested (=> instead of >= fex)
+  5560 antarus  take some advice and use AssertEqual/NotEqual
+  5596 antarus  set Id on tests
+
+
+tests/portage_dep/test_isjustname.py (Added)
+  5564 antarus  isjustname tests
+  5596 antarus  set Id on tests
+  5633 antarus  fix tabs with patch from Grobian and bug # 161911, fix
+                developing a bit
+
+
+tests/portage_dep/test_isvalidatom.py (Added)
+  5557 antarus  Commit unit tests, hey look THEY ARE BROKEN
+  5560 antarus  take some advice and use AssertEqual/NotEqual
+  5567 antarus  print the incorrect atom
+  5569 antarus  catch and validate new ValueError Exception
+  5571 antarus  Handle the exception in isvalidatom, change it to use a
+                portage exceptoin, thanks to Zac for pointing this out
+  5596 antarus  set Id on tests
+  5633 antarus  fix tabs with patch from Grobian and bug # 161911, fix
+                developing a bit
+
+
+tests/portage_dep/test_match_from_list.py
+  5560 antarus  take some advice and use AssertEqual/NotEqual
+  5596 antarus  set Id on tests
+
+
+tests/portage_util/test_grabdict.py (Added)
+  5557 antarus  Commit unit tests, hey look THEY ARE BROKEN
+  5596 antarus  set Id on tests
+
+
+tests/portage_util/test_normalizedPath.py (Added)
+tests/portage_util/test_stackDictList.py (Added)
+  5529 antarus  split out util tests
+  5560 antarus  take some advice and use AssertEqual/NotEqual
+  5596 antarus  set Id on tests
+
+
+tests/portage_util/test_stackDicts.py (Added)
+  5529 antarus  split out util tests
+  5547 antarus  More portage_util tests
+  5560 antarus  take some advice and use AssertEqual/NotEqual
+  5596 antarus  set Id on tests
+
+
+tests/portage_util/test_stackLists.py (Added)
+  5529 antarus  split out util tests
+  5549 antarus  add stack_lists checks
+  5560 antarus  take some advice and use AssertEqual/NotEqual
+  5596 antarus  set Id on tests
+
+
+tests/portage_util/test_uniqueArray.py (Added)
+tests/portage_util/test_varExpand.py (Added)
+  5529 antarus  split out util tests
+  5547 antarus  More portage_util tests
+  5596 antarus  set Id on tests
+
+
+tests/portage_util/test_util.py
+  5529 antarus  split out util tests
+  5530 antarus  remove monolithic test
+
+
+tests/portage_versions (Added)
+  5537 antarus  Add a bit of path mangling to allow deeper tests
+  5613 antarus  ignore py[co] in tests
+
+
+tests/portage_versions/__init__.py (Added)
+  5537 antarus  Add a bit of path mangling to allow deeper tests
+  5596 antarus  set Id on tests
+
+
+tests/runTests
+  5533 zmedico  Fix sys.path so that imports work correctly.
+
+
+tests/test_atoms.py
+  5523 zmedico  Make the tests pass.
+  5524 antarus  Fix Fail test
+  5525 antarus  Take Genone's suggestion and break the modules up into module
+                oriented fashion. Tests for portage.py go in portage/ and so
+                on and so forth...
+
+
+tests/test_atoms.py (from /main/trunk/tests/test_vercmp.py:5488) (Added)
+tests/test_vercmp.py (Removed)
+  5522 antarus  rework test import code, rename test_vercmp to be more
+                generic, add tests for =* glob matches
+
+
+tests/test_util.py
+  5522 antarus  rework test import code, rename test_vercmp to be more
+                generic, add tests for =* glob matches
+  5525 antarus  Take Genone's suggestion and break the modules up into module
+                oriented fashion. Tests for portage.py go in portage/ and so
+                on and so forth...
+
+
+=============================================================================
+2.1.2_rc4
+2006-12-22
+trunk revision 5359
+=============================================================================
+
+
+NEWS
+cnf/make.conf
+  5325 genone   New elog modules for dismerging messages into a single
+                file/mail
+
+
+bin/ebuild.sh
+  5244 zmedico  For bug #157369, clean when cleanup has been triggered by
+                changed timestamps. Also, allow FEATURES=keepwork to override
+                the ebuild mtime check.
+  5302 zmedico  For bug #158177, force configure scripts that automatically
+                detect ccache to respect FEATURES="-ccache". Thanks to Horst
+                Schirmeier <gentoo@schirmeier.com> for this suggestion.
+  5306 vapier   remove pointless redirects to /dev/null when using hasq()
+  5307 vapier   force environment.bz2 to be clobbered if it already exists
+  5347 zmedico  Fix the "help" phase so that it works without build dirs.
+  5350 zmedico  Use a pipe instead of a temp file for the depend phase.
+  5358 zmedico  Fix inverted EAPI default logic.
+
+
+bin/emerge
+  5231 zmedico  Go ahead and populate depgraph.mydbapi even when --emptytree
+                is enabled since it doesn't matter anymore (dep_check now
+                returns all deps anyway).
+  5232 zmedico  Move the reset of the per-root initializations into the loop.
+  5233 zmedico  Remove unused depgraph.match() method.
+  5234 zmedico  Use tuples for digraph nodes in order to avoid lots of
+                pointless join and split calls.
+  5235 zmedico  Split some global updates functions out of depgraph and use
+                them for depclean when necessary.
+  5245 zmedico  This patch cleans up the blocker validation logic. Unlike the
+                previous implementation, this one carefully considers each
+                parent/block package relationship in order to ensure that no
+                unresolved blocks slip through.
+  5246 zmedico  Don't attempt to enforce merge order unless the blocker
+                parent is actually a "merge" node.
+  5247 zmedico  Escape a newline from the previous commit.
+  5248 zmedico  For bug #128809, process blockers for all installed packages.
+                Due to the performance penalty incurred by additional
+                dep_check calls, this is only enabled with the --deep option.
+  5255 zmedico  For bug #128809, optimize dep_check calls and enable the
+                blocker detection by default since the performance now seems
+                acceptable.
+  5256 zmedico  Make sure the SLOT comes from the vardb instead of the portdb
+                (for multislot, etc..). Thanks to jakub for reporting.
+  5266 zmedico  Ignore blockers when "--buildpkgonly" is enabled.
+  5267 zmedico  Ensure that the root of the vdb exists before attempting to
+                lock it. Thanks to Flameeyes for reporting.
+  5268 zmedico  When there are multiple packages occupying the same slot,
+                only consider the one with the highest COUNTER. Thanks to
+                leio for reporting.
+  5269 zmedico  Fix a typo from the previous commit.
+  5270 zmedico  For bug #157823, don't forget to split the USE.
+  5272 zmedico  For bug #157823, ignore blocker collisions between two
+                packages that are already installed if no merge is currently
+                scheduled for either of those package slots. These blockers
+                will be handled as necessary the next time that a merge of
+                either package is triggered.
+  5275 zmedico  Centralize all of the vardb metadata mangling in FakeVartree.
+  5276 zmedico  Store dependency metadata in depgraph.mydbapi so that it can
+                be used in place of the portdb for optimized dep_check calls
+                in depgraph.validate_blockers().
+  5277 zmedico  Optimize dep_check calls in depgraph.validate_blockers() by
+                using a fakedbapi instance instead of the real pordbapi
+                (minimizes available matches).
+  5278 zmedico  For higher efficiency, call self.__int__() instead of
+                int(self).
+  5279 zmedico  For bug #157897, only let depgraph.create() inject "merge"
+                nodes into the final state dbapi.
+  5280 zmedico  For bug #157897, ensure that only "merge" nodes are stored in
+                digraph.pkg_node_map.
+  5282 zmedico  Track slot atom to digraph node mappings as the depgraph is
+                built. This mapping will be used to detect node collisions
+                for bug #157897.
+  5283 zmedico  Remove redundant digraph.pkg_node_map node insertions. Once
+                per digraph.create() call will cover all nodes.
+  5285 zmedico  For bug #157897, handle the case of multiple versions within
+                a single package slot have been pulled into the dependency
+                graph. If possible, the package that has already been pulled
+                in will be reused. Otherwise, an error message will advise
+                the user to mask an unwanted version.
+  5286 vapier   handle --cols when displaying blockers
+  5287 zmedico  For bug #157897, add slot collision handling in
+                depgraph.create(), since create() is called from places other
+                than select_dep().
+  5288 zmedico  Fix a typo from the previous commit.
+  5289 zmedico  Update the comment about depgraph.pkg_node_map since it now
+                maps all nodes added to the graph.
+  5290 zmedico  Use depgraph.pkg_node_map so simplify comparison against
+                existing nodes at the beginning of depgraph.create().
+  5291 zmedico  Fix the --onlydeps conditional logic in depgraph.create().
+                These aren't real nodes and shouldn't be added to the
+                digraph, etc...
+  5292 zmedico  Remove redundant priority handling since that's always
+                handled in select_dep() for nodes that have parents.
+  5293 zmedico  Remove pointless unpacking of the parent node.
+  5294 zmedico  Make --columns blockers output more consistent when --quiet
+                is not enabled.
+  5296 zmedico  Cache blocked slots for better efficiency.
+  5297 zmedico  For bug #157897, show parent nodes in order to help the user
+                decide about what action to take.
+  5304 zmedico  Make dep_check validate all depstring atoms in order to
+                prevent problems from occuring later due to unexpected
+                invalid atoms.
+  5308 zmedico  In depgraph.altlist(), pop as many leaf nodes as possible
+                when no relationship has been ignored. This can halve the
+                time taken for a large merge order calculation.
+  5309 zmedico  Don't optimize depgraph.altlist() in reversed mode since the
+                optimization destroys --tree ouput.
+  5310 zmedico  Add a comment about the previous commit.
+  5311 zmedico  Add --debug support for --depclean.
+  5312 zmedico  Do some minor cleanup of the --depclean code.
+  5313 zmedico  Make depclean skip empty depstrings.
+  5314 zmedico  Disable the spinner when --debug is enabled so that it
+                doesn't interfere.
+  5316 zmedico  Catch PortageException from portdbapi.aux_get since it can
+                happen when gpg is in FEATURES.
+  5317 zmedico  Just start with an empty dict in dep_check_trees since
+                nothing more is needed.
+  5318 zmedico  For bug #158354, make "No" the default response for unmerge
+                actions.
+  5321 zmedico  For bug #158503, allow --nodeps to override blockers.
+  5322 zmedico  For bug #158508, make --fetchonly display a list of packages
+                for which the fetch phase failed.
+  5324 zmedico  Use a separate digraph to store parent/child relationships
+                (PDEPEND relationships are not reversed) so that relationship
+                is always known in case a slot collision occurs.
+  5332 zmedico  Give the user some advice whenever an invalid dependency
+                string is encountered.
+  5333 zmedico  Fix the invalid dependency message so there's no confusion
+                about which package has the problem.
+  5335 zmedico  Fix broken exception handling syntax causing strange
+                exception reported in bug #158608. Thanks to grobian for help
+                troubleshooting.
+  5337 zmedico  For bug #158649, minimize portdb cache pulls for installed
+                packages when --nodeps is enabled. This patch also allows the
+                vardb lock to be released before doing any cache pulls (even
+                when --nodeps is not enabled), and updates the spinner while
+                the metadata is being pulled.
+  5339 zmedico  For bug #158558, ignore invalid depstrings for packages that
+                are being replaced anyway (otherwise the user would be forced
+                to manually unmerge the package).
+  5340 zmedico  When a removal phase fails, tell the user where the ebuild is
+                and advise them that the ebuild can be removed in order to
+                skip the removal phases.
+  5341 zmedico  For installed packages with invalid depstrings, tell the user
+                the location of the *DEPEND files.
+  5346 zmedico  Make emerge enable backward compatibility mode for
+                dep_check() calls on installed packages so that it can
+                gracefully invalid atoms or dep syntax.
+  5348 zmedico  For bug #158649, allow --buildpkgonly to bypass the fakedb
+                population like --nodeps does.
+  5349 zmedico  Revert the default choice for --ask --unmerge (bug #158354)
+                because people are complaining.
+
+
+bin/misc-functions.sh
+  5238 genone   adjust QA_* variable names for complex values of like
+                x86-fbsd
+
+
+bin/repoman
+  5228 zmedico  Remove all traces of FEATURES=cvs since code for that feature
+                no longer exists (apparently since portage-2.1).
+  5240 zmedico  Use portage.isvalidatom() for atom validation in repoman.
+  5243 zmedico  Clean up depstring/atom splitting and filtering.
+  5264 zmedico  Add an allow_blockers parameter to isvalidatom so that the
+                behavior is optional. Thanks to Brian Harring for the
+                suggestion.
+  5301 zmedico  Make repoman cache per-profile xmatch results.
+
+
+man/make.conf.5
+  5228 zmedico  Remove all traces of FEATURES=cvs since code for that feature
+                no longer exists (apparently since portage-2.1).
+
+
+pym/cache/flat_hash.py
+  5354 zmedico  When an unprivileged user runs portage (not in the portage
+                group), use metadata_overlay together with a volatile
+                in-memory cache module in order to implement cache writes.
+                This allows, for example, a user who's not in the portage
+                group to run `ebuild foo.ebuild digest` (issue reported by
+                Charlie Shepherd <masterdriverz@gentoo.org>).
+
+
+pym/cache/metadata_overlay.py
+  5338 zmedico  More intelligently handle CacheCorruption errors in the
+                writable cache.
+  5354 zmedico  When an unprivileged user runs portage (not in the portage
+                group), use metadata_overlay together with a volatile
+                in-memory cache module in order to implement cache writes.
+                This allows, for example, a user who's not in the portage
+                group to run `ebuild foo.ebuild digest` (issue reported by
+                Charlie Shepherd <masterdriverz@gentoo.org>).
+  5356 zmedico  Pass a cache instance into metadata_overlay since it doesn't
+                have enough information to construct one itself.
+  5357 zmedico  Make metadata_overlay use the autocommits attribute of the
+                underlying database.
+
+
+pym/cache/volatile.py (Added)
+  5355 zmedico  Add volatile cache module missing from the previous commit.
+
+
+pym/elog_modules/mod_mail_summary.py (Added)
+  5325 genone   New elog modules for dismerging messages into a single
+                file/mail
+  5343 zmedico  For bug #158658, fix the 'TypeError: int argument required'
+                that happens in the finalize() routine.
+
+
+pym/elog_modules/mod_save_summary.py (Added)
+  5325 genone   New elog modules for dismerging messages into a single
+                file/mail
+  5329 zmedico  Fix an import statement typo.
+
+
+pym/portage.py
+  5229 zmedico  Clean up vardbapi.aux_get().
+  5230 zmedico  Remove locking from dbapi.aux_update() implementations so
+                that the caller can handle locking instead.
+  5236 zmedico  Fix broken SLOT update logic in fakedbapi.cpv_inject().
+  5237 zmedico  Fix a type from the previous commit.
+  5239 zmedico  Add use.force support to dep_check for repoman especially.
+                Thanks to Flameeyes for reporting and tesing.
+  5249 zmedico  Avoid unnecessary dbapi.cp_list() calls inside cpv_expand().
+  5252 zmedico  Use dep_getcpv() inside dep_expand() for code sharing and
+                caching.
+  5253 zmedico  Cache the results of fakedbapi.match() calls and clear the
+                cache automatically when necessary.
+  5254 zmedico  Initialize the match cache in the bindbapi constructor.
+  5267 zmedico  Ensure that the root of the vdb exists before attempting to
+                lock it. Thanks to Flameeyes for reporting.
+  5273 zmedico  Make the fetch phase bail out if FETCHCOMMAND or
+                RESUMECOMMAND are missing. Thanks to Flameeyes for reporting.
+  5274 zmedico  All portage.fetch() to succeed even if FETCHCOMMAND and
+                RESUMECOMMAND aren't defined.
+  5281 zmedico  Move the biolerplate cpv_all() implementation from portdbapi
+                to dbapi.
+  5298 zmedico  Cache KEYWORDS and EAPI metadata values in order to speed up
+                portdbapi.gvisible() calls. This greatly improves repoman
+                performance (help emerge a little too).
+  5299 zmedico  Make sure eapi is defined in order to prevent a NameError.
+  5300 zmedico  Split ACCEPT_KEYWORDS before entering the loop for better
+                efficiency.
+  5304 zmedico  Make dep_check validate all depstring atoms in order to
+                prevent problems from occuring later due to unexpected
+                invalid atoms.
+  5305 zmedico  Make use_reduce raise an InvalidDependString exception for
+                use? conditionals that aren't followed by parenthesis and add
+                appropriate exception handling in dep_check.
+  5315 zmedico  Make portdbapi cache SLOT in addition to EAPI and KEYWORDS in
+                order to further optimize dep matching/selection.
+  5323 zmedico  Increase cache hits in portdbapi.xmatch().
+  5325 genone   New elog modules for dismerging messages into a single
+                file/mail
+  5326 zmedico  Make binarytree.move_ent() properly update PF.
+  5327 zmedico  For bug #158558, fix broken ebuild rename logic in
+                vardbapi.move_ent().
+  5328 zmedico  For bug #158558, make the unmerge phase do automatic cleanup
+                for broken vardbapi.move_ent() in portage versions before
+                2.1.2.
+  5330 zmedico  For bug #158608, don't attempt to use distlocks when it's
+                detected that the filesystem is readonly (unless
+                "skiprocheck" is in FEATURES for some strange reason).
+  5331 zmedico  Add missing newlines to the warning message that's printed
+                when the user has distlocks enabled together with skiprocheck
+                and the filesystem is readonly.
+  5340 zmedico  When a removal phase fails, tell the user where the ebuild is
+                and advise them that the ebuild can be removed in order to
+                skip the removal phases.
+  5342 zmedico  For bug #158632, make aux_get caching safe for missing values
+                in cache entries.
+  5344 zmedico  Use the return value from setdefault to avoid an extra dict
+                lookup.
+  5345 zmedico  Create a backward compatibility mode for dep_check() so that
+                emerge can use it to gracefully deal with installed packages
+                that have invalid atoms or dep syntax.
+  5347 zmedico  Fix the "help" phase so that it works without build dirs.
+  5350 zmedico  Use a pipe instead of a temp file for the depend phase.
+  5353 antarus  Remove two old functions, appear to be relics from 2.0.X
+                branch, no longer used by portage or gentoolkit or esearch
+  5354 zmedico  When an unprivileged user runs portage (not in the portage
+                group), use metadata_overlay together with a volatile
+                in-memory cache module in order to implement cache writes.
+                This allows, for example, a user who's not in the portage
+                group to run `ebuild foo.ebuild digest` (issue reported by
+                Charlie Shepherd <masterdriverz@gentoo.org>).
+  5356 zmedico  Pass a cache instance into metadata_overlay since it doesn't
+                have enough information to construct one itself.
+  5359 zmedico  Combine two default EAPI settings in portdbapi.aux_get().
+
+
+pym/portage_dep.py
+  5241 zmedico  Make isvalidatom() (and thus repoman) reject atoms containing
+                |() characters. Thanks to Brian Harring for the suggestion.
+  5242 zmedico  Add ? to the invalid atom characters.
+  5250 zmedico  Cache the results of match_from_list() calls.
+  5251 zmedico  Cache results of dep_getcpv() calls.
+  5260 zmedico  To minimize memory consumption and maximize performance, use
+                hash values for cache keys.
+  5262 zmedico  Don't collapse the tuple into a hash, since dict can use
+                __eq__ to avoid problems with hash collisions. Thanks to
+                Brian Harring for reporting.
+  5263 zmedico  For bug #157734, fix repoman isvalidatom() checks. Thanks to
+                Brian Harring for the patch.
+  5264 zmedico  Add an allow_blockers parameter to isvalidatom so that the
+                behavior is optional. Thanks to Brian Harring for the
+                suggestion.
+  5305 zmedico  Make use_reduce raise an InvalidDependString exception for
+                use? conditionals that aren't followed by parenthesis and add
+                appropriate exception handling in dep_check.
+  5345 zmedico  Create a backward compatibility mode for dep_check() so that
+                emerge can use it to gracefully deal with installed packages
+                that have invalid atoms or dep syntax.
+
+
+pym/portage_exec.py
+  5351 antarus  I hate docstrings
+
+
+pym/portage_update.py
+  5303 zmedico  Fix global updates error handling to prevent a traceback with
+                python-2.5 as reported in bug #158264.
+
+
+=============================================================================
+2.1.2_rc3
+2006-12-08
+trunk revision 5227
+=============================================================================
+
+
+bin/dispatch-conf
+  5136 zmedico  For bug #8423, make dispatch-conf preserve timestamps when
+                possible.
+
+
+bin/ebuild
+  5169 zmedico  For `ebuild --force digest`, exempt the depend phase from
+                Manifest checks.
+  5201 zmedico  For bug #157393, fix up ebuild path normalization so that
+                it's compatible with portdbapi handling and works properly
+                with symlinks (like crossdev creates).
+  5202 zmedico  Make sure the ebuild path is properly normalized.
+
+
+bin/ebuild.sh
+  5142 solar    - make sure QUIET mode is exported to the environment
+                properly when using -q mode.
+
+
+bin/emerge
+  5085 zmedico  For bug #155559, force depclean dep_check calls to preference
+                installed packages.
+  5086 zmedico  Use fake_vardb for cached aux_get calls.
+  5092 zmedico  Use mydbapi is None to eliminate the return_all_deps
+                parameter from dep_check and dep_zapdeps. The result is the
+                same and this way we avoid having an additional parameter
+                with overlapping meaning.
+  5095 zmedico  For depclean, just pass in None for mydbapi (instead of an
+                empty fakedbapi instance) since that's now supported.
+  5096 zmedico  Remove redundant package.provided handling that is now
+                covered by dep_wordreduce.
+  5097 zmedico  Remove more redundant package.provided handling that is now
+                covered by dep_wordreduce.
+  5101 zmedico  Allow the ROOT setting to come from make.conf. Thanks to
+                Daniel Barkalow <barkalow@iabervon.org> for this patch
+                (submitted on the gentoo-portage-dev mailing list).
+  5105 zmedico  For bug #155739, only check if a dep is in the args when
+                myroot == self.target_root.
+  5106 zmedico  Print a warning message if a user requests a package from
+                package.provided (since it won't be merged).
+  5107 zmedico  Enable PORTAGE_CONFIGROOT to be set via an new --config-root
+                option. Thanks to Daniel Barkalow <barkalow@iabervon.org> for
+                the initial patch (submitted on the gentoo-portage-dev
+                mailing list).
+  5118 zmedico  Fix a KeyError in emerge --info <pkg> when there is no
+                matching ebuild in the tree. Thanks to Bo ?\195?\152rsted
+                Andresen <bo.andresen@zlin.dk> for reporting.
+  5122 zmedico  For bug #156014, always round up the next kB so that it
+                doesn't show 0 kB when some small file still needs to be
+                fetched.
+  5173 zmedico  For bug #157134, make `emerge --digest` automatically reload
+                the config with FEATURES=digest enabled globally.
+  5174 zmedico  Fix up mtimedb["ldpath"] references broken by the previous
+                commit.
+  5180 zmedico  Remove unused depgraph.is_newer_ver_installed() method.
+  5184 zmedico  Remove dependence on the vartree api by using equivalent
+                vardbapi calls.
+  5185 zmedico  Only call calc_changelog if there is an installed version in
+                the same slot.
+  5189 zmedico  Use a fake vartree for depgraph calculations. This minimizes
+                the time that a lock needs to be held on the vardb, and
+                allows in-memory global updates when necessary.
+  5190 zmedico  Delete the depgraph when it's no longer needed.
+  5191 zmedico  Use FakeVartree for vardb lock/cache during depclean.
+  5192 zmedico  Allow depclean to silently skip packages unmerged behind it's
+                back.
+  5193 zmedico  Fix depclean so the fake vartree is used in dep_check calls.
+  5194 zmedico  Always silently ingnore missing packages during unmerge.
+  5195 zmedico  Remove all traces of the unmerge raise_on_missing parameter.
+  5196 zmedico  Fix indentation.
+  5206 zmedico  Share the same config instance between portagetree and
+                portdbapi instances since clone isn't needed here. Also,
+                trigger population of virtuals prior to cloning in emerge.
+                This reduces the number of times the virtuals are populated
+                from 3 to just 1.
+  5207 zmedico  Enable FakeVartree to populate the virtuals so that the vdb
+                doesn't have to be scanned separately.
+  5211 zmedico  s/zip/izip/ Thanks to Brian Harring for the suggestion.
+  5216 genone   Allow searching for action terms again
+  5218 zmedico  Avoid bogus 'Deprecated use of action' warnings for valid
+                commands such as `emerge -s sync`.
+  5219 zmedico  Simplfy deprecated action parsing logic.
+  5220 zmedico  For bug #157370, make `emerge --regen` cleanse stale cache
+                entries.
+  5221 zmedico  Delete the exception object after use.
+  5222 zmedico  Break out of the loop if a CacheError occurs.
+
+
+bin/emerge-webrsync
+  5154 zmedico  For consistent behavior in all timezones, make
+                emerge-webrsync use UTC time for decisions about which
+                snapshots to download.
+
+
+bin/etc-update
+  5135 zmedico  For bug #8423, make etc-update preserve timestamps when
+                possible.
+
+
+bin/misc-functions.sh
+  5114 zmedico  For bug #142993, make sure that chown and chgrp calls
+                preserve S_ISUID and S_ISGID mode bits.
+  5143 solar    - no point in forking a call to true when we can simply use
+                the bash internal of : for true
+  5164 vapier   drop RESTRICT=stricter since every aspect it covers can be
+                handled properly via other means
+
+
+bin/repoman
+  5167 zmedico  Make `repoman fix` work with the new ebuild Manifest checks
+                during depend phase.
+  5200 zmedico  Make repoman bail out if it's unable to generate the
+                Manifest.
+
+
+make.conf.txt (Added)
+  5146 genone   add ReST template to be used for
+                manpage/make.globals/make.conf.example generation later on
+  5147 genone   fix a few docutils errors
+  5148 genone   use a link in CXXFLAGS section (the typo caused it to be a
+                target)
+  5216 genone   Allow searching for action terms again
+
+
+man/ebuild.5
+  5168 zmedico  Update the RESTRICT=binchecks docs. Thanks to jakub for the
+                suggestion and antarus for the patch.
+
+
+pym/portage.py
+  5088 zmedico  Fix portdbapi.cpv_all() so that it actually returns a list of
+                all available ebuilds.
+  5092 zmedico  Use mydbapi is None to eliminate the return_all_deps
+                parameter from dep_check and dep_zapdeps. The result is the
+                same and this way we avoid having an additional parameter
+                with overlapping meaning.
+  5093 zmedico  Allow dep_wordreduce to mark things satisfied by
+                package.provided even when mydbapi is None.
+  5101 zmedico  Allow the ROOT setting to come from make.conf. Thanks to
+                Daniel Barkalow <barkalow@iabervon.org> for this patch
+                (submitted on the gentoo-portage-dev mailing list).
+  5114 zmedico  For bug #142993, make sure that chown and chgrp calls
+                preserve S_ISUID and S_ISGID mode bits.
+  5121 zmedico  For bug #150585, stack package.keywords incrementally so that
+                -keyword works as expected for any incremental variable. This
+                brings the gvisible and getmaskingstatus logic into sync so
+                that the confusing (masked by: ) message will not be
+                generated in cases where package.keywords contains -keyword
+                followed by keyword.
+  5123 zmedico  Allow -keyword to be matched since some ebuilds use it.
+                Thanks to Brian Harring reporting on bug #150585.
+  5129 zmedico  For bug #8423, allow the merge phase to overwrite untouched
+                config files and also allow the unmerge phase to unmerge
+                untouched config files.
+  5133 zmedico  Never overwrite an untouched config file and trigger config
+                protection instead (in case the new config has an unwanted
+                change). In cases where an installed package in the same slot
+                owns a protected file that will be merged, bump the mtime on
+                the installed file in order to ensure that it isn't unmerged.
+                Thanks to Ciaran McCreesh <ciaranm@ciaranm.org> for his
+                suggestion on bug #8423, comment #40.
+  5134 zmedico  Update the dblink.isprotected() docstring.
+  5150 zmedico  Always verify the ebuild checksums before executing it.
+                Thanks to solar for the suggestion and antarus for the
+                initial patch.
+  5151 zmedico  For manifest and digest phases, use a global variable to
+                temporarily exempt the depend phase from manifest checks (in
+                cache regeneration is triggered).
+  5152 zmedico  Temporarily exempt the depend phase during the help phase
+                also.
+  5153 zmedico  Avoid checking the same Manifest several times in a row
+                during a regen with an empty cache.
+  5155 zmedico  Only attempt to verify the Manifest if the ebuild is actually
+                in a portage tree.
+  5156 zmedico  Make sure that *all* of the ebuilds are listed in the
+                Manifest.
+  5157 zmedico  Make sure that all depend phases triggered by the digest
+                phase are exempt from digest checks.
+  5159 zmedico  Skip digest checks when digest is in features.
+  5160 zmedico  Make portage.digestgen() automatically exempt the depend
+                phase from Manifest checks so that it works for repoman
+                without triggering a digest verification failure.
+  5161 zmedico  Move the global statement out of the try block so that it's
+                clearly in scope for the finally block.
+  5166 zmedico  When portdbapi.aux_get() generates a KeyError in
+                portage.getmaskingstatus(), handle it by reporting
+                "corruption".
+  5171 zmedico  Use portage.chdir() instead of os.chdir() in order to avoid
+                an 'OSError: [Errno 2] No such file or directory' if the
+                working directory doesn't exist. Thanks to Caster for
+                reporting.
+  5178 zmedico  Implement fakedbapi.aux_update().
+  5197 zmedico  For bug #157385, enable portage.digestgen() to fetch any
+                distfiles for which there are no existing digests.
+  5198 zmedico  Fix broken SRC_URI logic from the previous commit.
+  5199 zmedico  Fix broken SRC_URI logic in doebuild.
+  5203 zmedico  Fix the 'TypeError: not all arguments converted during string
+                formatting' for bug #157385.
+  5206 zmedico  Share the same config instance between portagetree and
+                portdbapi instances since clone isn't needed here. Also,
+                trigger population of virtuals prior to cloning in emerge.
+                This reduces the number of times the virtuals are populated
+                from 3 to just 1.
+  5207 zmedico  Enable FakeVartree to populate the virtuals so that the vdb
+                doesn't have to be scanned separately.
+  5209 zmedico  Catch an exception instead of using a redundant os.access
+                call.
+  5212 zmedico  s/zip/izip/ some more
+
+
+pym/portage_dep.py
+  5175 zmedico  Make match_to_list = behavior consistent with >= and <= for
+                bug #152127.
+  5176 zmedico  Sync match_to_list >=, <=, etc.. code with the new = code.
+  5204 zmedico  Revert r5175 for bug #152127 since the original = behavior
+                seems more desirable. We can change the >= and <= behavior
+                instead.
+
+
+pym/portage_locks.py
+  5214 zmedico  Make all lock files hidden for bug #142369.
+
+
+pym/portage_util.py
+  5114 zmedico  For bug #142993, make sure that chown and chgrp calls
+                preserve S_ISUID and S_ISGID mode bits.
+  5115 zmedico  Fix apply_permissions logic for cases where mode is
+                unspecified.
+  5116 zmedico  Fix bit mask support when preserving S_ISUID and S_ISGID in
+                apply_permissions.
+  5117 zmedico  Really fix bit mask support when preserving S_ISUID and
+                S_ISGID in apply_permissions.
+  5119 zmedico  Use portage_data.lchown for compatibility.
+  5215 antarus  minor syntax changes ( in is faster than has_key ) and
+                docstrings
+
+
+pym/portage_versions.py
+  5205 zmedico  For bug #152127, make vercmp give less value to implcit .0,
+                so two versions that aren't literally equal are not
+                ambiguously given the same value (in sorting, for example).
+  5208 antarus  portage_versions lacks a header or copyright notice :x
+  5210 antarus  A quick docstring for vercmp
+
+
+tests (Added)
+  5213 antarus  Add pretty basic vercmp unit testing...need more cases
+
+
+tests/__init__.py (Added)
+  5213 antarus  Add pretty basic vercmp unit testing...need more cases
+  5217 antarus  add some portage_util tests
+  5227 zmedico  Indicate test failure with an exit code.
+
+
+tests/runTests (Added)
+  5213 antarus  Add pretty basic vercmp unit testing...need more cases
+  5227 zmedico  Indicate test failure with an exit code.
+
+
+tests/test_util.py (Added)
+  5217 antarus  add some portage_util tests
+
+
+tests/test_vercmp.py (Added)
+  5213 antarus  Add pretty basic vercmp unit testing...need more cases
+  5217 antarus  add some portage_util tests
+
+
+=============================================================================
+2.1.2_rc2
+2006-11-17
+trunk revision 5081
+=============================================================================
+
+
+NEWS
+  4779 zmedico  Add news about new-style virtuals being usable for bootstrap
+                deps on self.
+  4781 zmedico  Add news about package.use in profiles and default USE in
+                ebuilds via +flag in IUSE.
+  4800 zmedico  Add news about ACCEPT_LICENSE and package.license.
+  4822 genone   streamline portage pythonpath handling and add an override
+                analog to how the bash side does it
+  4884 zmedico  Rely on PYTHONPATH instead of PORTAGE_PYM_PATH for locating
+                portage's python modules, then fall back to an explicit
+                sys.path insertion if an ImportError occurs.
+  5081 zmedico  Revert ACCEPT_LICENSE support, since license group support is
+                a requirement and it remain unimplemented. This brings trunk
+                back into sync with the 2.1.2 branch.
+
+
+bin/archive-conf
+  4822 genone   streamline portage pythonpath handling and add an override
+                analog to how the bash side does it
+  4884 zmedico  Rely on PYTHONPATH instead of PORTAGE_PYM_PATH for locating
+                portage's python modules, then fall back to an explicit
+                sys.path insertion if an ImportError occurs.
+  4903 zmedico  For bug #116616, only run the post_process phase if
+                necessary.
+
+
+bin/chkcontents
+bin/clean_locks
+bin/emaint
+bin/env-update
+bin/fix-db.py
+bin/md5check.py
+bin/pkgname
+bin/portageq
+bin/regenworld
+bin/xpak
+  4822 genone   streamline portage pythonpath handling and add an override
+                analog to how the bash side does it
+  4884 zmedico  Rely on PYTHONPATH instead of PORTAGE_PYM_PATH for locating
+                portage's python modules, then fall back to an explicit
+                sys.path insertion if an ImportError occurs.
+
+
+bin/dispatch-conf
+  4822 genone   streamline portage pythonpath handling and add an override
+                analog to how the bash side does it
+  4881 zmedico  Just use stat instead of lstat for config protect, so that
+                broken symlinks are just ignored.
+  4884 zmedico  Rely on PYTHONPATH instead of PORTAGE_PYM_PATH for locating
+                portage's python modules, then fall back to an explicit
+                sys.path insertion if an ImportError occurs.
+  4887 zmedico  Add support for frozen config files for which updates are
+                automatically zapped. Thanks to Bo ?\195?\152rsted Andresen
+                for the initial patch from bug #151685.
+  4901 zmedico  For bug #129670, skip the replace-cvs and replace-wscomments
+                tests if the diff exit code indicates two two binary files
+                that differ.
+
+
+bin/dosed
+  4762 zmedico  Make dosed use sed -i instead of a temp file. Thanks to Tim
+                Cera for this patch from bug #152017.
+  4763 zmedico  Fix sed options from the previous commit so that it doesn't
+                create a backup file ending with "e". Thanks to grobian for
+                spotting this issue.
+
+
+bin/ebuild
+  4822 genone   streamline portage pythonpath handling and add an override
+                analog to how the bash side does it
+  4848 zmedico  Do not pass the "clean" parameter to doebuild since it causes
+                ${T} to be cleaned up when it shouldn't be. Thanks to
+                Mr_Bones_ for reporting.
+  4884 zmedico  Rely on PYTHONPATH instead of PORTAGE_PYM_PATH for locating
+                portage's python modules, then fall back to an explicit
+                sys.path insertion if an ImportError occurs.
+
+
+bin/ebuild.sh
+  4700 zmedico  Disable the ECLASS inherited illegally message during *rm
+                phases since it gives false alarms (bug #150442).
+  4701 zmedico  Use globing to match *rm phases from the last commit.
+  4920 zmedico  Enable RESTRICT=ccache. Thanks to drizzt for reporting.
+  4922 zmedico  Don't allow RESTRICT=ccache since it should work and if not
+                then it's a bug that ought to be fixed. Thanks to vapier.
+  4929 zmedico  Revert implicit rdepend behavior back to the way it was in
+                portage-2.0.51. Thanks to vapier for the patch. The original
+                change seems to have been an accidentally hunk (referencing
+                bug #58819) that was committed to cvs along with another
+                patch in revision 1.201.2.32 of ebuild.sh.
+
+
+bin/emerge
+  4683 zmedico  Fix a KeyError triggered by blockers in depgraph.display()
+                for bug #151331.
+  4697 zmedico  Fix the USE flag handling in depgraph.display() for bug
+                #151331, comment #5.
+  4698 zmedico  This patch implements intelligent navigation around blockers
+                in cases where the merge order can be adjusted (via hard
+                deps) such that two mutually blocking packages aren't
+                installed simultanously. This fixes bug #150879.
+  4699 zmedico  Fix display of nomerge nodes and --tree for ROOT!=/.
+  4722 zmedico  For bug #133908, prevent collisions in ${PKGDIR}/All/ by
+                automatically bumping colliding packages to
+                ${PKGDIR}/${CATEGORY}/ just before a collision would occur.
+                Newly built packages are always stored in ${PKGDIR}/All/,
+                should this be 100% compatible with previous behavior.
+  4726 zmedico  When unable to navigate around blockers, add them back to the
+                main digraph so that the --tree display can show them
+                properly. This fixes the KeyError reported in comment #15 of
+                bug #151331
+  4728 zmedico  Remove blocker nodes from the digraph prior to the merge
+                order calculation so that they don't trigger false circular
+                dependencies as reported in comment #17 of bug #151331.
+  4729 zmedico  Blockers that depend on merge order must be validated by
+                depgraph.altlist(reversed=False) before the reverse tree is
+                generated, since the validation won't work in reverse mode.
+  4730 zmedico  Fix altlist blocker validation logic so that the correct
+                nodes are added to the list when called in reverse mode.
+  4731 zmedico  Always add blockers with priority=digraph.SOFT so that
+                blockers with multiple parents can't trigger a circular deps
+                panick.
+  4732 zmedico  Make --depclean treat DEPEND as soft deps instead of forcing
+                the user to have all build time deps installed.
+  4733 zmedico  Use setdefault to avoid an extra dict lookup.
+  4735 zmedico  Stack use.mask/package.use.mask together at each level of the
+                profile for bug #151586, and do the same with
+                use.force/package.use.force.
+  4738 zmedico  Encapsulate altlist calls (for blockers that depend on merge
+                order) in validate_blockers().
+  4745 zmedico  Add more dependency priority levels for merge order
+                calculations. Previously, all installed deps were categorized
+                at the same level with other soft deps. Now there are 3
+                priority levels for soft deps: satisfied buildtime, satisfied
+                runtime, and other.
+  4746 zmedico  Fix a typo in xrange arguments from the previous commit.
+  4747 zmedico  Remove the unused system slot from DepPriority.
+  4748 zmedico  Fix --usepkg --newuse logic so that it doesn't throw a
+                KeyError if there's no matching ebuild in the tree.
+  4749 zmedico  Add __weakref__ to __slots__ so that weakref support isn't
+                disabled.
+  4750 zmedico  Don't initialize __weakref__ in the DepPriority constructor.
+  4751 zmedico  All packages to be added to the world favorites via
+                --noreplace, even when --ask is enabled. Thanks to leio for
+                reporting this issue.
+  4752 zmedico  Explicitly set the priority when a node is added to enforce
+                merge order for blocker avoidance.
+  4753 zmedico  Handle unresolvable blockers properly for bug #151822.
+  4756 zmedico  s/digraph.MEDIUM/DepPriority.MEDIUM/
+  4759 zmedico  Only call altlist() to validate blockers when necessary.
+  4761 zmedico  Remove special case of --emptytree in depgraph.display().
+                Thanks to Jason Stubbs for this patch from bug #152030.
+  4766 zmedico  Clean up the blocker validation logic so that "blocks" nodes
+                are no longer stored in the main digraph.
+  4769 zmedico  We there is a circular deps panic in reversed mode, do the
+                circular deps output without reversed mode since it should
+                reduce the noise level.
+  4772 zmedico  For bug #152175, trigger greedy --update behavior when an
+                atom matches a slot that isn't installed yet.
+  4773 zmedico  Apply the fix for bug #152175 to system/world greedy
+                behavior.
+  4774 zmedico  In greedy atom handlink, filter binary package for visiblity.
+  4775 zmedico  More filtering binary package for visiblity in greedy atom
+                handling.
+  4776 zmedico  Add nodes to the fakedb in depgraph.create instead of
+                depgraph.select_deps. It used to be in select_deps only for
+                the case of packages that depend on themselves for bootstrap,
+                but that hack isn't needed anymore because dep_check returns
+                all deps now.
+  4777 zmedico  Update the docs regarding delay of config.setinst calls for
+                bootstrap deps on old-style virtuals.
+  4778 zmedico  Remove redunant population of the fakedb in
+                depgraph.validate_blockers, since r4776 makes it unnecessary.
+  4783 zmedico  Also check keyword visibility via gvisible.
+  4788 zmedico  Fix visibility checks so that binary packages aren't masked
+                just because there is no matching ebuild in the tree.
+  4794 zmedico  Fix gcc version parsing once again for bug #137786. sigh. :)
+  4806 zmedico  Don't display the "Please update portage" message in --quiet
+                mode. Thanks to solar.
+  4822 genone   streamline portage pythonpath handling and add an override
+                analog to how the bash side does it
+  4823 genone   rename getmaskingreason() to getpmaskcomment() to clarify its
+                function, report each license as a separate mask instead of
+                combining them all together into a single value for
+                getmaskingstatus()
+  4827 genone   show licenses or pointer to license files on 'masked by'
+                message
+  4858 zmedico  Avoid a TypeError with emerge -kN when there's no matching
+                ebuild.
+  4872 zmedico  Use a tuple for __slots__ so that it's immutable.
+  4884 zmedico  Rely on PYTHONPATH instead of PORTAGE_PYM_PATH for locating
+                portage's python modules, then fall back to an explicit
+                sys.path insertion if an ImportError occurs.
+  4906 zmedico  Implement --color < y | n > for bug #42115 and deprecate
+                --nocolor. When --color is not specified, rely on the old
+                NOCOLOR variable and/or stdout auto-detection.
+  4918 zmedico  Silently omit info_pkgs that aren't installed. Thanks to
+                solar.
+  4926 zmedico  Fix --ignore-default-opts for bug #153980.
+  4947 zmedico  Prevent the --newuse check in depgraph.create() that is
+                intended for the ebuild type from being done on binary
+                packages (which can lead to a KeyError). The --newuse check
+                for binaries is elsewhere (in select_dep).
+  4949 zmedico  Ensure that sys-apps/portage is as close as possible to the
+                beginning of the merge list. This is accomplished by merging
+                it before any soft deps that it may have.
+  4950 zmedico  Remove "update portage before proceeding" message that is no
+                longer relevant.
+  4951 zmedico  Remove old code the used to bump portage near the top of the
+                merge list. It's ineffective now that a complete depgraph is
+                built.
+  4953 zmedico  Make sure the node is still in the graph so that a KeyError
+                can't happen.
+  4955 zmedico  For bug #154223, bridge new-style virtuals into old-style
+                virtuals in order to prevent old-style virtuals from making
+                new-style virtuals invisible.
+  4962 zmedico  Simplify the new-style -> old-style virtuals bridge by doing
+                it implicitly for all virtuals instead of explicit scanning
+                for available new-style virtuals.
+  4968 zmedico  Fix validate_blockers() so that a package doesn't block
+                itself via a virtual that it provides.
+  4970 zmedico  Print the number of upgrades, downgrades, etc. next to size
+                of downloads. Thanks to Bo ?\195?\152rsted Andresen
+                <bo.andresen@zlin.dk> for the initial patch from bug #153847.
+  4974 zmedico  Thanks to Bo ?\195?\152rsted Andresen <bo.andresen@zlin.dk>
+                for this output fix for bug #153847.
+  4976 zmedico  Plug some holes in the blocker validation logic so that
+                nothing can slip through.
+  4978 zmedico  Remove some stray blocker validation logic.
+  4983 zmedico  For bug #154207, add a note about package.provided to the
+                depclean warning message.
+  4984 zmedico  Add --newuse back to the suggested options in the depclean
+                warning message, since it's still needed in some cases.
+  5004 zmedico  Fix emerge --sync with a cvs:// uri so that it runs
+                /etc/portage/bin/post_sync like it would with a normal
+                rsync:// uri. Thanks to drizzt for reporting.
+  5006 zmedico  Fix initial cvs checkout logic for bug #100478.
+  5008 zmedico  For initial gentoo-x86 checkout, if $PORTDIR exists and is
+                empty then remove it so that the gentoo-x86 checkout can
+                replace it.
+  5012 zmedico  Fix depgraph.pkg_node_map so that it properly supports $ROOT.
+  5023 zmedico  For bug #154919, when depclean is unable to resolve
+                dependencies, notify the user that it may be necessary to
+                manually uninstalled packages that no longer exist in the
+                portage tree.
+  5028 zmedico  For bug #154989, lock /var/db/pkg while determining which
+                packages to unmerge, then release the lock. The lock will be
+                reacquired/released for each individual unmerge, allowing
+                opportunities for other processes to acquire it.
+  5032 zmedico  Use try/finally to ensure that locks are properly released in
+                emergelog().
+  5038 zmedico  For bug #154897, show a summary of fetch restrictions if
+                there are any.
+  5040 zmedico  Cache depgraph.altlist results, since altlist is called
+                multiple times and can be time consuming for a large
+                depgraph.
+  5042 zmedico  Make fakedbapi support generic metadata instead of just
+                slots.
+  5049 zmedico  Only reload the config if global updates have actually been
+                performed.
+  5051 zmedico  Automatically convert --ask to --pretend when the user
+                doesn't have the privileges for --ask. Thanks to Daniel
+                Barkalow <barkalow@iabervon.org> for the initial patch
+                (submitted on gentoo-portage mailing list).
+  5053 zmedico  Don't try to lock the vdb unless privileges are sufficient.
+  5057 zmedico  Add a note about removal of new-style virtuals in the
+                depclean output.
+  5063 zmedico  Revert the depclean message, since new-style virtuals will
+                now be kept.
+  5069 zmedico  Fix a typo that prevents emerge --clean from working
+                properly. Thanks to leio for reporting.
+  5071 zmedico  For bug #155484, apply PORTAGE_NICENESS as soon as possible
+                (especially before global updates).
+  5081 zmedico  Revert ACCEPT_LICENSE support, since license group support is
+                a requirement and it remain unimplemented. This brings trunk
+                back into sync with the 2.1.2 branch.
+
+
+bin/emerge-webrsync
+  4959 zmedico  For bug #154220, run /etc/portage/bin/post_sync at the end of
+                emerge-webrsync.
+
+
+bin/fixpackages
+  4822 genone   streamline portage pythonpath handling and add an override
+                analog to how the bash side does it
+  4884 zmedico  Rely on PYTHONPATH instead of PORTAGE_PYM_PATH for locating
+                portage's python modules, then fall back to an explicit
+                sys.path insertion if an ImportError occurs.
+  5073 zmedico  Make fixpackages use PORTAGE_NICENESS.
+  5075 zmedico  s/settings/mysettings/ typo
+
+
+bin/misc-functions.sh
+  4737 zmedico  Add back the -v option for tar (removed for bug #151146) in
+                dyn_package(), but don't enable -v when --quiet is enabled.
+  4863 zmedico  Use mtree to save/restore bsd file flags before/after prepall
+                and installation. Thanks to Diego Petten?\195?\178 for this
+                patch (related to bug #153109).
+
+
+bin/prepall
+  4863 zmedico  Use mtree to save/restore bsd file flags before/after prepall
+                and installation. Thanks to Diego Petten?\195?\178 for this
+                patch (related to bug #153109).
+
+
+bin/repoman
+  4792 zmedico  Add support for masking of packages via ACCEPT_LICENSE and
+                /etc/portage/package.license. Thanks to Jason Stubbs for the
+                initial patch from bug #17367.
+  4822 genone   streamline portage pythonpath handling and add an override
+                analog to how the bash side does it
+  4884 zmedico  Rely on PYTHONPATH instead of PORTAGE_PYM_PATH for locating
+                portage's python modules, then fall back to an explicit
+                sys.path insertion if an ImportError occurs.
+  5081 zmedico  Revert ACCEPT_LICENSE support, since license group support is
+                a requirement and it remain unimplemented. This brings trunk
+                back into sync with the 2.1.2 branch.
+
+
+cnf/dispatch-conf.conf
+  4887 zmedico  Add support for frozen config files for which updates are
+                automatically zapped. Thanks to Bo ?\195?\152rsted Andresen
+                for the initial patch from bug #151685.
+
+
+cnf/make.conf.sparc-fbsd.diff (Added)
+  4724 genone   add make.conf diff for sparc-fbsd arch (from Uberlord)
+
+
+cnf/make.globals
+  4734 zmedico  Merge package.use and USE from make.defaults together at each
+                level of the profile stack. This is analogous to how use.mask
+                and package.use.mask are planned to be merged for bug
+                #151586.
+
+
+man/ebuild.5
+  4889 vapier   recommend people use `emake` rather than `make` when
+                installing with DESTDIR
+
+
+man/emerge.1
+  4907 zmedico  Document the new --color < y | n > option for bug #42115.
+
+
+man/make.conf.5
+  4797 zmedico  Add some ACCEPT_LICENSE docs.
+  4813 zmedico  Remove ACCEPT_LICENSE docs until they're really implemented.
+  4912 zmedico  Fix the USE_ORDER docs for bug #153764. Thanks to Alec Warner
+                for the initial patch.
+
+
+man/portage.5
+  4780 zmedico  Add package.use to the list of files supported in profiles.
+  4798 zmedico  Put the package.keywords docs in alphabetical order with the
+                others.
+  4799 zmedico  Add some package.license docs.
+  4803 zmedico  Add package.license to the list of files.
+  4813 zmedico  Remove ACCEPT_LICENSE docs until they're really implemented.
+
+
+pym/cache/anydbm.py
+pym/cache/flat_list.py
+pym/cache/metadata_overlay.py
+pym/cache/sql_template.py
+pym/cache/sqlite.py
+  4821 zmedico  Reverse the relationship between __contains__ and has_key in
+                all cache classes since python handles the "in" operator more
+                efficiently than a has_key method call.
+
+
+pym/cache/flat_hash.py
+  4808 zmedico  Enable recognition of _mtime_ that doesn't rely on cache
+                mtime mangling.
+  4821 zmedico  Reverse the relationship between __contains__ and has_key in
+                all cache classes since python handles the "in" operator more
+                efficiently than a has_key method call.
+
+
+pym/cache/metadata.py
+  4708 zmedico  Add a missing method parameter.
+  4820 zmedico  Test for basestring instead of types.DictType so that the
+                test more generic.
+
+
+pym/cache/template.py
+  4807 zmedico  Remove paths from _eclasses_ serialization in the cache. This
+                makes the mtimes of the eclasses the only thing that
+                distinguishes them, but the probablility of collision is
+                negligible. This same _eclasses_ format will be used to
+                serialize eclass mtimes in cache that is distributed via the
+                rsync mirrors. The deserialization code can handle mixtures
+                of both the old and new formats.
+  4814 zmedico  Improve reconstruct_eclasses error handling.
+  4815 zmedico  For the time being, write a variation of the old _eclass_
+                format so that cache written only forces a regen for older
+                versions of portage rather than a ValueError due to failed
+                long() conversion.
+  4818 zmedico  For full compatibility with older versions of portage, write
+                the path in the serialized _eclasses_ when possible.
+  4821 zmedico  Reverse the relationship between __contains__ and has_key in
+                all cache classes since python handles the "in" operator more
+                efficiently than a has_key method call.
+  4855 zmedico  Add backward compatibility code for cache modules that
+                override has_key instead of __contains__.
+
+
+pym/cache/util.py
+  4924 zmedico  When transferring cache after sync, compare all metadata to
+                make sure it is identical (don't trust _mtime_ and _eclasses_
+                alone). Local tests show that this can add approximately 15%
+                more time to the metadata update, but it's needed for things
+                like bug #153591.
+  4925 zmedico  Make sure trg is defined.
+
+
+pym/dispatch_conf.py
+  4822 genone   streamline portage pythonpath handling and add an override
+                analog to how the bash side does it
+  4850 zmedico  Don't bother to insert /usr/lib/portage/pym into sys.path
+                from inside a module. That's the caller's job.
+
+
+pym/eclass_cache.py
+  4807 zmedico  Remove paths from _eclasses_ serialization in the cache. This
+                makes the mtimes of the eclasses the only thing that
+                distinguishes them, but the probablility of collision is
+                negligible. This same _eclasses_ format will be used to
+                serialize eclass mtimes in cache that is distributed via the
+                rsync mirrors. The deserialization code can handle mixtures
+                of both the old and new formats.
+  4818 zmedico  For full compatibility with older versions of portage, write
+                the path in the serialized _eclasses_ when possible.
+  4819 zmedico  Fix broken is_eclass_data_valid comparison logic.
+
+
+pym/emergehelp.py
+  4851 zmedico  Add --with-bdeps to emerge --help output.
+  4852 zmedico  Update help for --deep.
+  4853 zmedico  Update help for greedy behavior of --update.
+  4908 zmedico  Add --color < y | n > help output for bug #42115.
+  4909 zmedico  Remove broken nocolor() call, since thats handled internally
+                by the output module anyway.
+
+
+pym/output.py
+  4771 zmedico  Allow an empty PROMPT_COMMAND for bug #152157.
+  4782 zmedico  For bug #152157, don't send a redundant escape sequence with
+                ${PROMPT_COMMAND}.
+  4906 zmedico  Implement --color < y | n > for bug #42115 and deprecate
+                --nocolor. When --color is not specified, rely on the old
+                NOCOLOR variable and/or stdout auto-detection.
+
+
+pym/portage.py
+  4704 zmedico  Simplify binarytree.getname().
+  4712 zmedico  Trigger binarytree population on bindbapi.cpv_all() calls.
+  4722 zmedico  For bug #133908, prevent collisions in ${PKGDIR}/All/ by
+                automatically bumping colliding packages to
+                ${PKGDIR}/${CATEGORY}/ just before a collision would occur.
+                Newly built packages are always stored in ${PKGDIR}/All/,
+                should this be 100% compatible with previous behavior.
+  4734 zmedico  Merge package.use and USE from make.defaults together at each
+                level of the profile stack. This is analogous to how use.mask
+                and package.use.mask are planned to be merged for bug
+                #151586.
+  4735 zmedico  Stack use.mask/package.use.mask together at each level of the
+                profile for bug #151586, and do the same with
+                use.force/package.use.force.
+  4741 zmedico  Filter empty elements in cumulative env-update variables.
+                Thanks to Brian Harring for this patch from bug #151694.
+  4744 zmedico  Eliminate an unnecessary string concatenation.
+  4745 zmedico  Add more dependency priority levels for merge order
+                calculations. Previously, all installed deps were categorized
+                at the same level with other soft deps. Now there are 3
+                priority levels for soft deps: satisfied buildtime, satisfied
+                runtime, and other.
+  4760 zmedico  For userpriv, call setgroups with all groups that the portage
+                user belongs to (bug #137610).
+  4786 zmedico  Optimize config.setcpv so that it only calls regenerate when
+                necessary. Thanks to Jason Stubbs for the initial patch from
+                bug #17367.
+  4787 zmedico  Use reset instead of regenerate (revert part of the previous
+                commit) in order to properly clear the env layer of the
+                config.
+  4789 zmedico  Call load_infodir before the setup phase for binary packages
+                so that USE is properly set.
+  4790 zmedico  Don't put empty incrementals in the environment.
+  4791 zmedico  Do put empty incrementals in the environment if they are
+                already set.
+  4792 zmedico  Add support for masking of packages via ACCEPT_LICENSE and
+                /etc/portage/package.license. Thanks to Jason Stubbs for the
+                initial patch from bug #17367.
+  4793 zmedico  s/str_matches/acceptable_licenses/ typo
+  4801 zmedico  Make config.load_infodir also load the data into the env
+                layer in order to ensure that it has preference over what may
+                have been there.
+  4802 zmedico  Don't limit the size of USE in config.load_infodir.
+  4804 zmedico  Don't put -* in the env layer, since that layer isn't part of
+                the incremental stacking in regenerate.
+  4805 zmedico  In getmaskingstatus(), add missing check for * in
+                acceptable_licenses.
+  4810 zmedico  Disable ACCEPT_LICENSE support until the details of license
+                groups are decided and implemented.
+  4817 zmedico  For bug #152726, ignore hidden files in vardbapi.cp_list().
+  4823 genone   rename getmaskingreason() to getpmaskcomment() to clarify its
+                function, report each license as a separate mask instead of
+                combining them all together into a single value for
+                getmaskingstatus()
+  4824 genone   need a mutable config instance to use setcpv
+  4826 genone   add function getlicensetexts() to extract license texts
+                relevant to a given cpv (to be used by emerge masked by
+                display)
+  4827 genone   show licenses or pointer to license files on 'masked by'
+                message
+  4828 genone   show licenses or pointer to license files on 'masked by'
+                message
+  4863 zmedico  Use mtree to save/restore bsd file flags before/after prepall
+                and installation. Thanks to Diego Petten?\195?\178 for this
+                patch (related to bug #153109).
+  4867 zmedico  Prevent an attribute error AttributeError for invalid binary
+                packages for which there is no CATEGORY data.
+  4869 zmedico  Don't forget to continue for invalid binpkgs.
+  4877 zmedico  For bug #153295, do a sanity check for non-string types in
+                config.environ().
+  4879 zmedico  For getmaskingstatus messages, don't assume ARCH is a valid
+                keyword, since that assumption is not necessarily correct for
+                operating systems other than Linux. Thanks to Diego
+                Petten?\195?\178 for reporting.
+  4885 zmedico  Fix a KeyError when the profile doesn't define default USE.
+  4893 zmedico  For bug #153295, make load_infodir ignore files that contain
+                null bytes.
+  4899 zmedico  For bug #153282, automatically find the owner package(s) in
+                the event of a fatal file collision (since the collision is
+                fatal, the performance hit doesn't matter).
+  4916 zmedico  For bug #153951, fail with a simple "Permission denied" error
+                if the merge phase doesn't have write access to $ROOT.
+  4955 zmedico  For bug #154223, bridge new-style virtuals into old-style
+                virtuals in order to prevent old-style virtuals from making
+                new-style virtuals invisible.
+  4957 zmedico  Make config.add_new_virtuals() work properly even if
+                self.virtuals has previously been initialized.
+  4962 zmedico  Simplify the new-style -> old-style virtuals bridge by doing
+                it implicitly for all virtuals instead of explicit scanning
+                for available new-style virtuals.
+  4966 zmedico  Minimize getvirtuals() calls and dict lookups inside
+                dep_virtual().
+  4980 zmedico  s/grabdict/grabdict_package/ for bug #63429.
+  5002 zmedico  Make digestcheck() fail if an ebuild isn't listed in the
+                Manifest. Thanks to pva for reporting.
+  5010 zmedico  For bug #154554, validate all profile virtuals atoms.
+  5021 zmedico  For bug #154921, prevent an IndexError when a + is in USE.
+  5027 zmedico  For bug #154989, use a single lock on /var/db/pkg since finer
+                grained locking is unnecessary and often insufficient.
+  5030 zmedico  Use try/finally to ensure that locks are properly released in
+                portdbapi.aux_get().
+  5033 zmedico  Use try/finally to ensure that locks are properly released in
+                dblink.unmerge().
+  5034 zmedico  Remove reentrance support for dblink.lockdb() since it's no
+                longer used and it won't necessarily work correctly now that
+                a global vdb lock is used.
+  5036 zmedico  For bug #154986, show the usual "Filesize does not match
+                recorded size" message even for fetch restricted files.
+  5042 zmedico  Make fakedbapi support generic metadata instead of just
+                slots.
+  5044 zmedico  Remove useless unmerge() call after collision-protect has
+                prevented anything from being merged.
+  5046 zmedico  Fix a lock file leak.
+  5048 zmedico  Make portage.global_updates() return any updates that may
+                have been performed.
+  5055 zmedico  For bug #141118, make dep_check do recursive expansion of
+                new-style virtuals.
+  5061 zmedico  Pull in the new-style virtuals and install them so that the
+                vdb has complete standalone dep info, in case a portage tree
+                isn't available.
+  5062 zmedico  For bug #141118, make dep_zapdeps assign zero cost to
+                new-style virtuals.
+  5064 zmedico  Update the _expand_new_virtuals docstring with a not about
+                zero cost for new-style virtuals.
+  5066 zmedico  Fix _expand_new_virtuals so that it doesn't allow any virtual
+                deps to go unaccounted for.
+  5067 zmedico  Integrate old-style virtuals handling into
+                _expand_new_virtuals() and prefer new-style over old-style
+                whenever they are available.
+  5081 zmedico  Revert ACCEPT_LICENSE support, since license group support is
+                a requirement and it remain unimplemented. This brings trunk
+                back into sync with the 2.1.2 branch.
+
+
+pym/portage_checksum.py
+  4972 zmedico  Thanks to Chris White for these portage_checksum docstrings.
+  5031 zmedico  Use try/finally to ensure that locks are properly released in
+                perform_checksum().
+
+
+pym/portage_const.py
+  4792 zmedico  Add support for masking of packages via ACCEPT_LICENSE and
+                /etc/portage/package.license. Thanks to Jason Stubbs for the
+                initial patch from bug #17367.
+  4809 zmedico  Add ACCEPT_LICENSE back to incrementals so that profiles can
+                affect it.
+  5081 zmedico  Revert ACCEPT_LICENSE support, since license group support is
+                a requirement and it remain unimplemented. This brings trunk
+                back into sync with the 2.1.2 branch.
+
+
+pym/portage_data.py
+  4760 zmedico  For userpriv, call setgroups with all groups that the portage
+                user belongs to (bug #137610).
+
+
+pym/portage_dep.py
+  4987 zmedico  Thanks to Chris White for these portage_dep docstrings.
+  4999 zmedico  Thanks again to Chris White for these additional portage_dep
+                docstrings.
+
+
+pym/portage_manifest.py
+  4743 zmedico  Make empty digest-* files 0 bytes instead of 1 byte. Thanks
+                to Sven Wegener for reporting this.
+
+
+pym/portage_util.py
+  4718 zmedico  Make grabdict incremental, so that keys occuring multiple
+                times will stack up instead of overwritting eachother. Thanks
+                to Sven Wegener for this suggestion.
+  4719 zmedico  Simplify and optimize grabdict. Thanks to Brian Harring for
+                suggesting this.
+  4736 zmedico  Add -* support to stack_lists() and use dict.pop() for
+                removal of flags when appropriate.
+  4742 zmedico  Fix CONFIG_PROTECT so that is works with symlinked
+                directories for bug #151502.
+  4881 zmedico  Just use stat instead of lstat for config protect, so that
+                broken symlinks are just ignored.
+
+
+=============================================================================
+2.1.2_pre3
+2006-10-13
+trunk revision 4679
+=============================================================================
+
+
+NEWS
+  4599 zmedico  Add news about slot deps.
+  4609 zmedico  Add news about major bug fixes in 2.1.2.
+  4629 zmedico  Add news about multiple inheritance support in profiles.
+
+
+RELEASE-NOTES
+  4610 zmedico  Add a release note about --with-bdeps.
+  4611 zmedico  Add a heading for portage-2.1.2.
+
+
+bin/dosed
+  4660 zmedico  Use -e instead of -a for better cross-shell compatibility.
+                Thanks to exg.
+
+
+bin/ebuild.sh
+  4657 blubb    disable path globbing when creating metadata keys; bug
+                150866; thanks to brian harring for the patch
+  4677 zmedico  Always `unset DEPEND RDEPEND PDEPEND IUSE` prior to sourcing
+                the ebuild in order to ensure correct interaction during the
+                process of sourcing. Thanks to exg for reporting this issue.
+  4679 zmedico  Implement per-package default USE flags at the ebuild and
+                profile levels for bug #61732.
+
+
+bin/emerge
+  4566 zmedico  Don't try to match call best_match_to_list() on "blocks"
+                nodes for bug #149576.
+  4567 zmedico  Emulate old --update world/system behavior for bug #149527.
+  4571 zmedico  Add medium priority level into the digraph (in addition to
+                the existing hard and
+  4572 zmedico  Fix depgraph.altlist() so that it can identify a group of
+                nodes that completely satisfy eachothers non-soft deps. This
+                should complete the fix for bug #149881.
+  4573 zmedico  Remove unnecessary set creation.
+  4576 zmedico  In depgraph.altlist(), use a recursive fuction to gather
+                groups of nodes that RDEPEND on eachother.
+  4577 zmedico  Remove a len(nodes) == 1 test that's never True.
+  4578 zmedico  Refector depgraph.altlist() reverse/ignore_priority handling.
+  4579 zmedico  Add a digraph.NONE constant to represent no priority.
+  4580 zmedico  Print a message about make.globals if PORTDIR is undefined.
+  4582 zmedico  Use 01775 permissions for subdirectories of PORTAGE_TMPDIR,
+                and 0755 permissions for other directories (bug #149062).
+  4586 zmedico  When gathering a group of nodes to merge (with circular
+                RDEPEND), make sure not to prematurely merge any nodes that
+                have unsatisfied hard deps.
+  4589 zmedico  Don't apply the sticky bits until we have a complete plan for
+                bug #149062.
+  4595 zmedico  For bug #4698, use slot deps to ensure that all installed
+                slots are automatically updated.
+  4600 zmedico  For bug #150178, print an error message when emerge is called
+                with both --config and --pretend.
+  4605 zmedico  For bug #48195, fall back to the installed packages when
+                there are no other choices. Global updates are automatically
+                performed on *DEPEND if necessary in order to clean up stale
+                atoms (we do single packages as necessary because it's too
+                time consuming to do the whole vdb at once).
+  4606 zmedico  Reject installed packages if they have a matching masked
+                ebuild in the tree.
+  4608 zmedico  Delete some temporary variables after use.
+  4612 zmedico  Fix package type assumptions in depgraph.display() for bug
+                #150359.
+  4613 zmedico  Remove redunant quotes for bug #150381. This change is
+                related to the shlex posix mode used to fix bug #14215.
+  4619 zmedico  Make system/world less greedy for bug #150251.
+  4620 zmedico  Fix another bad package type assumption in
+                depgraph.display().
+  4621 zmedico  For bug #150361, implement greedy matching of command line
+                atoms against relevant installed slots. This patch allows a
+                subset of installed slots to be pulled in via operators such
+                as > or <.
+  4624 zmedico  Clean up depgraph.select_files() to use one list of tuples
+                instead 2 separate lists.
+  4628 zmedico  Generate the depgraph.args_keys list _before_ building the
+                graph.
+  4632 zmedico  Remove unused PORTAGE_CALLER=emerge from the environment.
+  4641 zmedico  Make --newuse not imply --update anymore because that
+                restriction is unnecessary.
+  4642 zmedico  Make --tree not imply --pretend anymore so that people can
+                put it in EMERGE_DEFAULT_OPTS.
+  4649 zmedico  Fix breakage in generation of favorites list for bug #150754.
+  4654 zmedico  Move PORTAGE_BUILDDIR in to a category subdirectory and clean
+                up the category directory if empty (while holding lock). This
+                this will help avoid PORTAGE_BUILDDIR collisions for parallel
+                builds and will also hack around bug #150454.
+  4658 zmedico  Use grabfile instead of cat to display the gentoo-release
+                file.
+  4659 zmedico  Append PORTAGE_RSYNC_EXTRA_OPTS after the default options for
+                bug #150883.
+  4675 zmedico  For bug #151238, fix --with-bdeps logic so that it works
+                correctly with --onlydeps.
+  4678 zmedico  For bug #151082, don't allow installed packages to
+                inappropriately satisfy packages that have been explicitly
+                requested as arguments.
+  4679 zmedico  Implement per-package default USE flags at the ebuild and
+                profile levels for bug #61732.
+
+
+bin/etc-update
+  4645 zmedico  Add $ROOT and $PORTAGE_CONFIGROOT support for etc-update.
+                Thanks to Jonathan Adamczewski <jadamcze@utas.edu.au> for
+                this patch from bug #150370.
+
+
+bin/misc-functions.sh
+  4653 vapier   do not abort for the time being with lazy bindings and setuid
+                apps and FEATURES=stricter
+  4676 zmedico  For bug #151146, don't use tar's --verbose option during the
+                package phase since it doesn't work the same way anymore in
+                tar-1.15.92 (new args have been tested with both gnu
+                tar-1.15.92 and bsdtar-1.3.1-r1).
+
+
+bin/portageq
+  4633 zmedico  Remove unused PORTAGE_CALLER=portageq from the environment.
+
+
+bin/quickpkg
+  4570 zmedico  For bug #149781, exclude symlinks to directories when
+                creating binary package with quickpkg.
+
+
+bin/repoman
+  4604 zmedico  Make repoman generate a syntax error if a slot dep is used
+                with EAPI == 0.
+  4630 zmedico  For repoman, hide the vardbapi from dep_zapdeps.
+  4631 zmedico  Use a local_config flag to replace PORTAGE_CALLER == repoman
+                conditionals.
+  4636 zmedico  Fix typo s/upper/lower/.
+  4646 zmedico  Print a more useful error message for bug #150488.
+  4650 zmedico  Remove an unnecessary assumption preventing the use of CVS
+                for an overlay.
+  4651 zmedico  Don't lock repoman_settings because it needs to be mutable.
+  4679 zmedico  Implement per-package default USE flags at the ebuild and
+                profile levels for bug #61732.
+
+
+cnf/make.conf
+man/make.conf.5
+  4618 zmedico  For bug #140021, remove autoaddcvs from the docs. Thanks to
+                exg for this patch.
+
+
+cnf/make.globals
+  4614 zmedico  Remove redundant quotes from PORTAGE_RSYNC_OPTS.
+  4679 zmedico  Implement per-package default USE flags at the ebuild and
+                profile levels for bug #61732.
+
+
+man/emerge.1
+  4568 zmedico  Fix misspelling of dependencies for bug #149645.
+  4639 zmedico  Remove outdated mention of --update in the --deep docs.
+  4640 zmedico  Document greedy atoms for the --update option.
+  4663 zmedico  Escape quotes for bug #150932.
+
+
+man/portage.5
+  4626 zmedico  Remove use.default documentation since we don't use it
+                anymore. Thanks to Arfrever Frehtes Taifersar Arahesis for
+                this patch from bug #149608.
+  4627 zmedico  Remove one more reference to use.defaults.
+
+
+pym/portage.py
+  4571 zmedico  Add medium priority level into the digraph (in addition to
+                the existing hard and
+  4572 zmedico  Fix depgraph.altlist() so that it can identify a group of
+                nodes that completely satisfy eachothers non-soft deps. This
+                should complete the fix for bug #149881.
+  4575 zmedico  Fix priority logic in digraph.add().
+  4579 zmedico  Add a digraph.NONE constant to represent no priority.
+  4581 zmedico  Use 755 permissions for ${PORTAGE_WORKDIR}/distdir (bug
+                #149062).
+  4582 zmedico  Use 01775 permissions for subdirectories of PORTAGE_TMPDIR,
+                and 0755 permissions for other directories (bug #149062).
+  4583 zmedico  For userpriv support, chown files in ${T} if necessary after
+                priveleged phases.
+  4584 zmedico  Don't set the gid unnecessarily on $PORTAGE_BUILDDIR/distdir.
+  4585 zmedico  Make PORTAGE_BUILDDIR and subdirectories group writable for
+                now (reverts some of the changes from bug #149062). One major
+                problem is that the first phase (setup) is often run as root.
+                We need a way to tell portage about a less privileged user
+                that may need to be given permission on files and
+                directories.
+  4587 zmedico  Remove redundant PORTAGE_BUILDDIR creation.
+  4588 zmedico  Properly write all fifo and device nodes to CONTENTS for bug
+                #144781. Code to parse these entries has already in place and
+                they are never unmerged.
+  4589 zmedico  Don't apply the sticky bits until we have a complete plan for
+                bug #149062.
+  4590 zmedico  Fix a typo for the file mode in ${T}.
+  4591 zmedico  Don't create /cvs-src since the cvs.eclass will do that
+                automatically.
+  4594 zmedico  Add support for slot based dep matching in all dbapi derived
+                classes. The supported syntax is ${CATEGORY}/${PN}:${SLOT}
+                (identical to that used by paludis and pkgcore).
+  4603 zmedico  Don't call varexpand inside getconfig for env.d/profile.env
+                values.
+  4615 zmedico  For bug #150377, make virtual preferences in a profile
+                override the preferences of parent profiles.
+  4616 zmedico  Stack negative user virtuals in the correct order for
+                incremental behavior.
+  4622 zmedico  Make the merge phase automatically invalidate the
+                ${PORTAGE_BUILDDIR}/.installed flag since it may move files
+                out of the image directory.
+  4623 zmedico  Make the .installed invalidation conditional on srcroot and
+                destroot being located on the same filesystem (st_dev).
+  4625 zmedico  Remove the single parent constraint in profiles.
+  4631 zmedico  Use a local_config flag to replace PORTAGE_CALLER == repoman
+                conditionals.
+  4637 zmedico  Remove unnecessary config.reset() calls in
+                portage.create_trees().
+  4638 zmedico  Catch UnpicklingError when loading the mtimedb (reported by
+                marienz).
+  4643 zmedico  Avoid unnecessary population of the bintree by populating it
+                as late as possible.
+  4644 zmedico  Simplify the needlessly complex virtuals preferencing logic
+                that lead to bug #150377.
+  4648 zmedico  Only unlink .installed after the collision-protect has
+                completed successfully (reported by axxo).
+  4652 zmedico  Add more self.modifying() checks in order to detect
+                modifcations to locked config objects.
+  4654 zmedico  Move PORTAGE_BUILDDIR in to a category subdirectory and clean
+                up the category directory if empty (while holding lock). This
+                this will help avoid PORTAGE_BUILDDIR collisions for parallel
+                builds and will also hack around bug #150454.
+  4655 zmedico  For bug #150121, generate an error in digestcheck() if a file
+                is found that is not listed in the Manifest.
+  4661 zmedico  Use contents to avoid unnecessary ldconfig calls for bug
+                #136488.
+  4662 zmedico  Make an mtime change force an ldconfig run, since it's
+                possible that pre/postinst made changes in lib dirs (noted by
+                Brian Harring).
+  4664 zmedico  Fix the new env-update lib dirs logic to properly account for
+                $ROOT.
+  4679 zmedico  Implement per-package default USE flags at the ebuild and
+                profile levels for bug #61732.
+
+
+pym/portage_dep.py
+  4593 zmedico  Share duplicate code between dep_getkey() and dep_getcpv().
+  4594 zmedico  Add support for slot based dep matching in all dbapi derived
+                classes. The supported syntax is ${CATEGORY}/${PN}:${SLOT}
+                (identical to that used by paludis and pkgcore).
+  4598 zmedico  Improve best_match_to_list() and include support for slot
+                deps.
+
+
+pym/portage_manifest.py
+  4656 zmedico  Make manifest2AuxfileFilter() slightly more efficient and
+                also ignore any hidden files.
+
+
+pym/portage_update.py
+  4596 zmedico  Just use a simple replace for the needlessly complex
+                dep_transform function. This will make it compatible with
+                slot deps.
+  4597 zmedico  Fix package moves/slotmoves to work with slot deps.
+  4607 zmedico  In update_dbentries(), use != rather than "is not" to make
+                sure that updates never occur unnecessarily.
+  4617 zmedico  Fix dep_transform breakage (regression from r4596).
+  4647 zmedico  Only do a slotmove on a slot dep atom if the slotmove atom
+                has no operator (otherwise there's not enough information to
+                perform the slotmove).
+
+
+pym/portage_util.py
+  4574 zmedico  Optimize varexpand for bug #149900.
+  4601 zmedico  For bug #150163, remove unnecessary validation of
+                new_protect_filename() parameters.
+  4602 zmedico  For bug #14215, put the shlex parser in posix mode so that it
+                properly recognizes escaped quotes.
+  4603 zmedico  Don't call varexpand inside getconfig for env.d/profile.env
+                values.
+
+
+=============================================================================
+2.1.2_pre2
+2006-09-29
+trunk revision 4565
+=============================================================================
+
+
+bin/ebuild
+  4480 zmedico  Properly close the caches before reloading portage.
+
+
+bin/ebuild.sh
+  4495 blubb    use EBUILD_SH_ARGS instead of $*; bug 148615
+  4556 zmedico  Fix broken [ -z "" ] test. Thanks to Volkov Peter
+                <pva@gentoo.org> for this patch from bug #149494.
+  4557 zmedico  Fix quoting of ${D} in make arguments for einstall(). Thanks
+                to Volkov Peter <pva@gentoo.org> for this patch from bug
+                #149494.
+
+
+bin/emerge
+  4467 zmedico  Reimplement parallel-fetch so that it simply spawns `emerge
+                --fetch --resume` via portage_exec.spawn. This prevents
+                potential issues with shared file descriptors and unsafe
+                forks as discussed in bug #147516. This patch makes sure that
+                the spawned emerge process does not write to emerge.log or
+                the mtimedb.
+  4468 zmedico  Use mtimedb.filename == None to disable mtimedb writes
+                (instead of /dev/null).
+  4469 zmedico  Close the parallel-fetch log file descriptor when it's no
+                longer needed.
+  4471 zmedico  Ensure that the parent process gets the first fetch when
+                parallel-fetch is enabled.
+  4472 zmedico  Thanks to Jason Stubbs for this patch from bug #147766 which
+                enables creation of a full and complete depgraph, leaving no
+                dependencies unaccounted for. This will allow more accurate
+                merge order and proper detection of circular dependencies!
+  4473 zmedico  Thanks again to Jason Stubbs for this patch from bug #147766
+                which represents PDEPEND relationships withing the depgraph
+                as reverse soft dependencies.
+  4474 zmedico  Idendify soft deps in emerge --debug output.
+  4475 zmedico  Allow packages matched by something in package.provided to be
+                explicitly merged by the user.
+  4479 zmedico  This is a new --tree implementation by Jason Stubbs, from bug
+                #147766.
+  4482 zmedico  For consistency, pass ignore_soft_deps into
+                digraph.hasallzeros().
+  4486 zmedico  Thanks to Jason Stubbs for this patch from bug #16365 which
+                invalidates any blocker that is made irrelevant by a package
+                upgrade.
+  4487 zmedico  Fix depgraph.validate_blockers() logic so that
+                match_from_list works correctly.
+  4488 zmedico  Add a docstring for depgraph.validate_blockers().
+  4489 zmedico  Remove an inaccurate comment.
+  4490 zmedico  Add a comment about old-style virtuals inside
+                depgraph.validate_blockers().
+  4491 zmedico  Prevent an IndexError caused by blocker nodes splitting to 3
+                items instead of 4.
+  4492 zmedico  Prevent --update and/or --deep style behavior when the user
+                hasn't specified them. In these cases a full depgraph isn't
+                desired and we have to ignore the installed deps that are now
+                returned from dep_check.
+  4493 zmedico  Fix another IndexError due to an assumption that digraph
+                nodes split into at least 4 parts.
+  4494 zmedico  Allow packages specified on the command line to be
+                retroactively upgraded from "nomerge" to "merge" nodes.
+  4496 zmedico  Revert r4495, since conversion from nomerge to merge may put
+                the depgraph into an inconsistent state du to USE flag
+                mismatch. This can be solved by checking all args prior to
+                marking packages as nomerge.
+  4500 zmedico  For compatibility with float timestamps in python-2.5,
+                convert st_mtime attributes to long wherever portage expects
+                1s resolution.
+  4505 zmedico  Make it possible, once again, to use --noreplace to add a
+                package to the world file.
+  4507 zmedico  Ensure that soft_dep is a plain boolean (not vardb match
+                results).
+  4508 zmedico  Never allow packages explicitly requested on the command line
+                to be tagged "nomerge" unless --noreplace has been specified.
+                This patch accomplishes the same goal as r4494 but without
+                the potential for causing inconsistency in the depgraph.
+  4509 zmedico  Pass in the correct arg= value to select_dep.
+  4511 zmedico  Remove outdated "Unable to run required binary" messages that
+                are now unreachable.
+  4512 zmedico  Move PORTAGE_BUILDDIR locking out of doebuild and into emerge
+                in order to ensure that emerge maintains it's lock through
+                all phases.
+  4513 zmedico  Always check the return value of doebuild_environment().
+  4518 zmedico  Remove doebuild_environment return value checks since it no
+                raises and exception if necessary.
+  4522 zmedico  In order to ensure correct merge order such that build time
+                dependencies will really be usable, don't treat RDEPEND as
+                soft_deps. Thanks for Jason Stubbs for recognizing this
+                issue.
+  4523 zmedico  Remove depgraph params for depclean since it no longer uses
+                the depgraph.
+  4524 zmedico  Clean up and simplify depgraph params logic. This fixes bug
+                #148893.
+  4526 vapier   print errors to stderr, not stdout
+  4527 zmedico  Make `emerge world` (without --deep) work as expected for bug
+                #149092.
+  4528 zmedico  Check the dep_check return value and fail with a message if
+                an error has occurred.
+  4529 zmedico  Clean up the logic a little for bug #149092.
+  4539 zmedico  Add SLOT support to fakedbapi then use it for depgraph
+                blocker handling and dep_zapdeps preference selection.
+  4540 zmedico  Make sure that all packages are in the dbapi when doing the
+                blocker validation.
+  4541 zmedico  Fix --update so that it updates direct dependencies for bug
+                #149208.
+  4546 zmedico  Convert emerge option parsing to use python's optparse
+                module. This patch makes the minimum changes necessary for
+                the conversion and is supposed to be 100% compatible with
+                previous parsing behavior.
+  4547 zmedico  Convert myopts into a dictionary so that it can be used for
+                more that boolean flags.
+  4548 zmedico  Add a --with-bdeps=[y,n] option for bug #148870.
+  4549 zmedico  Add missing calls to iteritems() from the last commit.
+  4550 zmedico  Store myopts in the mtimedb as a list for backward
+                compatibility.
+  4551 zmedico  Use dict.pop(k, None) to delete items if they exist.
+  4552 zmedico  Remove some unreachable code.
+  4553 zmedico  Properly treat myopts as a dict.
+  4555 zmedico  Fix inverted --with-bdeps logic.
+  4560 zmedico  Allow options contained in EMERGE_DEFAULT_OPTS to be
+                overridden by the real command line options.
+
+
+bin/etc-update
+  4476 zmedico  Turn off file name globbing during expansion of ${find_opts}
+                for bug #148115.
+
+
+bin/pkgmerge (Removed)
+bin/pkgmerge.new (Removed)
+  4519 zmedico  Remove pkgmerge since it's apparent that nobody uses it (it's
+                been broken for a long time, anyway).
+
+
+bin/portageq
+  4483 zmedico  Make portageq exit with nonzero status when called
+                incorrectly.
+  4484 zmedico  Make portageq exit successfully for -h or --help.
+
+
+bin/prepstrip
+  4559 zmedico  Move installed sources into ${CATEGORY} subdirectories in
+                order to prevent collisions for bug #149491.
+
+
+man/emerge.1
+  4561 zmedico  Document the new --with-bdeps option.
+
+
+man/make.conf.5
+  4463 vapier   document FEATURES=buildsyspkg #147729
+  4563 zmedico  Document the new COLLISION_IGNORE variable.
+  4564 zmedico  Update installsources docs for bug #149491.
+  4565 zmedico  Update CONFIG_PROTECT docs to reflect that files are now
+                supported.
+
+
+pym/cache/anydbm.py
+pym/cache/fs_template.py
+pym/cache/metadata_overlay.py
+pym/cache/sql_template.py
+pym/cache/template.py
+pym/cache/util.py
+  4470 zmedico  Replace relative imports with absolute imports for forward
+                compatibility with python 2.6.
+
+
+pym/cache/flat_hash.py
+  4470 zmedico  Replace relative imports with absolute imports for forward
+                compatibility with python 2.6.
+  4499 zmedico  Convert stat timestamps to long for compatibility with
+                python-2.5, which returns floats for timestamps.
+  4501 zmedico  Use fstat to when retrieve cache timestamps and avoid a race.
+  4502 zmedico  Improve and simplify __getitem__ error handling.
+  4504 zmedico  Use finally: to ensure that the file is closed properly.
+  4506 zmedico  Move the open call out of the inner try block.
+  4545 zmedico  Catch a ValueError caused by corrupt cache for bug #149134.
+
+
+pym/cache/flat_list.py
+  4470 zmedico  Replace relative imports with absolute imports for forward
+                compatibility with python 2.6.
+  4500 zmedico  For compatibility with float timestamps in python-2.5,
+                convert st_mtime attributes to long wherever portage expects
+                1s resolution.
+
+
+pym/cache/metadata.py
+  4470 zmedico  Replace relative imports with absolute imports for forward
+                compatibility with python 2.6.
+  4501 zmedico  Use fstat to when retrieve cache timestamps and avoid a race.
+
+
+pym/cache/sqlite.py
+  4470 zmedico  Replace relative imports with absolute imports for forward
+                compatibility with python 2.6.
+  4498 zmedico  Allow cache.sqlite to use sqlite3 from python-2.5, if
+                available.
+  4503 zmedico  Don't use LazyLoad for cache pulls because it causes a race
+                condition.
+
+
+pym/eclass_cache.py
+pym/portage_update.py
+  4500 zmedico  For compatibility with float timestamps in python-2.5,
+                convert st_mtime attributes to long wherever portage expects
+                1s resolution.
+
+
+pym/output.py
+  4554 zmedico  Call sys.stdout.flush() after print statements so that output
+                has the correct order when multiple processes output to a
+                shared pipe.
+
+
+pym/portage.py
+  4464 zmedico  In portage.commit_mtimedb(), use the commit() method when
+                possible, so that the mtimedb is only rewritten when it has
+                been modified.
+  4468 zmedico  Use mtimedb.filename == None to disable mtimedb writes
+                (instead of /dev/null).
+  4472 zmedico  Thanks to Jason Stubbs for this patch from bug #147766 which
+                enables creation of a full and complete depgraph, leaving no
+                dependencies unaccounted for. This will allow more accurate
+                merge order and proper detection of circular dependencies!
+  4477 zmedico  Fix digraph.debug_print inverted hard/soft logic.
+  4478 zmedico  Fix fetch resume logic for bug #145601 and document the
+                meaning of the "fetched" variable.
+  4479 zmedico  This is a new --tree implementation by Jason Stubbs, from bug
+                #147766.
+  4481 zmedico  Fix digraph.hasallzeros() breakage.
+  4482 zmedico  For consistency, pass ignore_soft_deps into
+                digraph.hasallzeros().
+  4485 zmedico  As suggested by vapier, send emerge -fp output to stdout and
+                make it work together with --quiet.
+  4494 zmedico  Allow packages specified on the command line to be
+                retroactively upgraded from "nomerge" to "merge" nodes.
+  4496 zmedico  Revert r4495, since conversion from nomerge to merge may put
+                the depgraph into an inconsistent state du to USE flag
+                mismatch. This can be solved by checking all args prior to
+                marking packages as nomerge.
+  4500 zmedico  For compatibility with float timestamps in python-2.5,
+                convert st_mtime attributes to long wherever portage expects
+                1s resolution.
+  4510 zmedico  Move PORTAGE_LOG_FILE initialization from doebuild to
+                prepare_build_dirs.
+  4512 zmedico  Move PORTAGE_BUILDDIR locking out of doebuild and into emerge
+                in order to ensure that emerge maintains it's lock through
+                all phases.
+  4513 zmedico  Always check the return value of doebuild_environment().
+  4514 zmedico  Lock PORTAGE_BUILDDIR all the way through prerm, unmerge, and
+                postrm.
+  4515 zmedico  Only lock PORTAGE_BUILDDIR if the ebuild exists (otherwise we
+                don't run prerm and postrm).
+  4516 zmedico  Make doebuild_environment raise an exception so that we never
+                have to check the return value.
+  4518 zmedico  Remove doebuild_environment return value checks since it no
+                raises and exception if necessary.
+  4520 zmedico  Fix portage.pkgmerge() so that it locks files and directories
+                when in use.
+  4521 zmedico  Use the same directories for binary package merges as would
+                be used for source based merges (since the normal
+                PORTAGE_BUILDDIR is already used by the setup, preinst, and
+                postinst phases anyway).
+  4524 zmedico  Clean up and simplify depgraph params logic. This fixes bug
+                #148893.
+  4525 zmedico  For bug #149028, don't lock the tbz2 file because the
+                filesytem could be readonly or shared by a cluster.
+  4539 zmedico  Add SLOT support to fakedbapi then use it for depgraph
+                blocker handling and dep_zapdeps preference selection.
+  4542 zmedico  Revert dep_zapdeps fakedbapi usage as per comment #31 on bug
+                #147766.
+  4543 zmedico  In dep_zapdeps preference selection, use package names
+                instead of the real atoms for an initial rough match against
+                installed packages. More specific preference selection is
+                handled later via slot and version comparison. Thanks to
+                Jason Stubbs for this patch from bug #147766.
+  4558 zmedico  Allow env.d file names with 3 characters. This is a
+                regression from r4451.
+  4562 zmedico  For bug #149412, add a COLLISION_IGNORE user config option
+                that behaves similar to CONFIG_PROTECT_MASK, but for
+                collision-protect.
+
+
+pym/portage_data.py
+  4530 zmedico  Add a warning about the portage group and the possiblility of
+                exploits for bug #149062.
+
+
+=============================================================================
+2.1.2_pre1
+2006-09-15
+trunk revision 4462
+=============================================================================
+
+
+bin/dispatch-conf
+  4461 zmedico  For bug #14321, make dispatch-conf scan for individual files
+                listed in CONFIG_PROTECT.
+
+
+bin/emerge
+  4459 zmedico  For bug #14321, make emerge scan for individual files listed
+                in CONFIG_PROTECT.
+
+
+bin/etc-update
+  4460 zmedico  For bug #14321, make etc-update scan for individual files
+                listed in CONFIG_PROTECT.
+
+
+bin/repoman
+  4462 zmedico  Add CATEGORY to the list of readonly variables.
+
+
+cnf/make.conf.sh.diff (Added)
+  4432 vapier   diff for superh
+
+
+man/make.conf.5
+  4443 vapier   note that you need to use an absolute path for ROOT #147427
+                by Brad Plant
+
+
+man/portage.5
+  4429 zmedico  Include a note about RESTRICT="fetch" in docs for local
+                mirrors (see bug #37455). Thanks to Carlo for reporting.
+
+
+pym/portage.py
+  4430 zmedico  In dblink.isowner(), correct the logic to test the path
+                itself (via lstat) rather than the referant in the case of
+                symlinks.
+  4431 zmedico  For bug #80846, prevent false collisions caused by symlinks.
+                Thanks to Thomas Bettler <bettlertho@sis.unibe.ch> for the
+                initial patch.
+  4434 zmedico  Add KDEDIRS to colon_separated env-update vars as requested
+                by Carlo.
+  4441 zmedico  For correct LINGUAS handling, don't export empty USE_EXPAND
+                variables unless the user config exports them as empty.
+                Thanks to Harald van Dijk <truedfx@gentoo.org> for this patch
+                from bug #147428.
+  4442 zmedico  Use configdict["env"].clear() instead of manual deletion
+                because the result is the same and it's much more efficient.
+  4450 zmedico  Simplify the confmem logic so that it's easier to read.
+  4451 zmedico  Move all env.d file name filtering into a single loop.
+  4452 zmedico  Add support for SPACE_SEPARATED and COLON_SEPARATED in
+                /etc/env.d/ so that hard coded values are not required.
+  4453 zmedico  When it's detected that a previously remembered update has
+                been accepted, remove it from confmem.
+  4458 zmedico  For bug #14321, add support for individual files in
+                CONFIG_PROTECT and CONFIG_PROTECT_MASK.
+
+
+pym/portage_locks.py
+  4446 zmedico  In unhardlink_lockfile(), make sure not to touch lockfilename
+                unless we really have a lock. See bug #147453.
+  4447 zmedico  Remove all traces of atexit hardlock cleanup code, since it
+                doesn't work correctly anyway.
+  4448 zmedico  Simplify portage_locks.hardlink_is_mine() so that it only
+                checks the number of links. Nothing more is needed.
+  4449 zmedico  Remove an unused hardlink_active() function.
+
+
+pym/portage_update.py
+  4433 zmedico  Fix a broken call to new_protect_filename for bug #147010.
+                This is a regression from r4400 (fix for bug #146289).
+
+
+pym/portage_util.py
+  4458 zmedico  For bug #14321, add support for individual files in
+                CONFIG_PROTECT and CONFIG_PROTECT_MASK.
+
+
+=============================================================================
+2.1.1
+2006-09-08
+trunk revision 4425
+=============================================================================
+
Index: /vendor/portage/current/DEVELOPING
===================================================================
--- /vendor/portage/current/DEVELOPING	(revision 3419)
+++ /vendor/portage/current/DEVELOPING	(revision 3419)
@@ -0,0 +1,67 @@
+Code Guidelines
+---------------
+A few code guidelines to try to stick to, please comment of none of these make
+sense, they are pretty basic and mostly apply to old code.  However for people
+who are looking at current code, they make take up bad habits that exist in the
+current codebase.
+
+Strings
+-------
+Try not to use the functions in the string module, they are deprecated.
+
+string.join(<iterable>," ")
+
+should be replaced with:
+
+" ".join(<iterable>)
+
+and:
+
+string.split(string, delimeter)
+
+should be replaced with:
+
+string.split(delimeter)
+
+Nearly all other methods in string work on string objects and have similar calling
+conventions.
+
+Comparisons
+-----------
+
+if foo == None
+
+should be replaced with:
+
+if foo is not None:
+
+Is not does a reference comparison (address1 = address2 basically) and 
+the == forces a by value compare (with __eq__())
+
+Dict Lookups
+------------
+
+Try not to use has_key, you can use
+
+if foo in dict
+
+instead of if dict.has_key(foo)
+
+Also don't do stuff like:
+
+if foo in dict and dict[foo]:
+
+Generally you can do two things here, if you are messing with defaults..
+
+dict.get(foo, some_default)
+
+will try to retrieve foo from dict, if there is a KeyError, will insert foo
+into dict with the value of some_default.  This method is preferred in cases where
+you are messing with defaults:
+
+try:
+	dict[foo]
+except KeyError:
+	dict[foo] = default_value
+
+The get call is nicer (compact) and faster (try,except are slow).
Index: /vendor/portage/current/NEWS
===================================================================
--- /vendor/portage/current/NEWS	(revision 3419)
+++ /vendor/portage/current/NEWS	(revision 3419)
@@ -0,0 +1,75 @@
+News (mainly features/major bug fixes)
+
+portage-2.1.2
+-------------
+
+* Add ** as new token for package.keywords to bypass the keyword visibility layer
+* Ebuilds support default USE flags via +flag in IUSE.
+* New-style virtuals are now usable for packages that depend on themselves for
+  bootstrap.
+* Profiles support multiple inheritance and package.use.
+* CONFIG_PROTECT and CONFIG_PROTECT_MASK both support files (not just
+  directories).
+* Collision protection handles symlinks properly.
+* Dependencies can be satisfied by installed packages that do not have matching
+  ebuilds in the portage tree or overlay.
+* Emerge automatically ignores blockers that are made irrelevant by an upgrade.
+* Emerge supports "reverse blocker detection" which means that the blockers of
+  installed packages will always be respected.
+* Emerge builds a complete dependency graph in order to ensure correct merge
+  order and detection of circular dependencies.
+* The world and system sets allow automatic update of all installed slots.
+* DEPEND atoms support SLOT dependencies of the form ${CATEGORY}/${PN}:${SLOT}.
+* Development: Extend PYTHONPATH support to allow overriding the hardcoded 
+  /usr/lib/portage/pym for development/testing purposes
+* New "finalize" hook for elog modules enabling modules to perform actions on 
+  shutdown (like dispatching collected messages).
+* New elog modules mail_summary and save_summary that act like the mail/save
+  modules except that they merge messages from multiple packages in a single
+  file/mail.
+* New QA loglevel and matching eqawarn function
+* `ebuild foo test` now always runs src_test if available
+* If DOC_SYMLINK_DIR is set portage installs symlinks to html documention there
+* FEATURES="test" automatically implies USE="test".
+
+portage-2.1.1
+-------------
+
+* Profiles support use.force, package.use.force, and package.use.mask files.
+
+portage-2.1 (ongoing via pre releases)
+------------
+
+* FEATURES="confcache" integration; global caching to speed up configure calls, 
+  requires dev-util/confcache
+* elog framework and accompanying modules for logging ebuild warnings, errors
+  and general notices. Collects eerror/ewarn/elog/einfo messages.
+* New elog function (should replace einfo in many cases)
+* version syntax enhancements allowing multiple suffixes and a new 'cvs'
+  version prefix for denoting "live sources" ebuilds.
+* config files as directories enabling more flexible settings management.
+* Addition of an register_die_hook method that allows ebuild/eclasses to
+  register functions to be called for better debugging on errors.
+* Addition of pre and post user hookable functions for each ebuild phase, accessible 
+  via portage bashrc.  Example would be pre_src_unpack .
+* cache refactoring- runtime improvement from 35% -> 65%.
+* Intelligently handle and display USE_EXPAND-based IUSE variables.
+* FEATURES="parallel-fetch".  Download in parallel to compilation.
+* Include a "changed or new" USE flag output when --verbose isn't specified.
+* Support for splitting out debug information into separate files in
+  /usr/lib{,32,64}.
+* exec subsystem refactoring (now with less bugs!)
+* Added sha256 and rmd160 hashes for digests/manifests
+* Make --emptytree only apply to ${ROOT} rather than always including /.
+* Allow packages to be upgraded that are only depended on via a
+  "|| ( =cat/pkg-1* =cat/pkg-2* )" construct.
+* Ebuild output is no longer cut off early when using PORT_LOGDIR.
+* Distfiles indirection- $DISTFILES access goes through a tmp dir to fail
+  access to files not listed in SRC_URI.
+* Emerge now uses --resume to restart itself after portage upgrade.
+* Atomic file updates via the new atomic_ofstream class.
+* Global updates and fixpackages performance optimizations.
+* Tests show that file locking is now more reliable.
+* A bash call stack is printed when an ebuild dies in ebuild.sh.
+* New rsync option handling by using a generic PORTAGE_RSYNC_EXTRA_OPTS variable
+* Manifest2 support that will allow digest-* files to be eliminated from the tree.
Index: /vendor/portage/current/RELEASE-NOTES
===================================================================
--- /vendor/portage/current/RELEASE-NOTES	(revision 3419)
+++ /vendor/portage/current/RELEASE-NOTES	(revision 3419)
@@ -0,0 +1,47 @@
+Release Notes; upgrade information mainly.
+Features/major bugfixes are listed in NEWS
+
+portage-2.1.2
+==================================
+
+* Depending on the number of packages installed, users may notice a difference
+  in the time taken for dependency calculations.  This performance penalty is
+  due to the addition of important new features which include the ability to
+  detect reverse blockers, the building of a complete dependency graph, and the
+  ability to use installed packages to satisify dependencies even after their
+  ebuilds have been removed from the portage tree.
+* emerge does not necessarily update build time dependencies that are not
+  strictly required.  See the --with-bdeps option in the emerge(1) man page.
+
+portage-2.1.1
+==================================
+
+* emerge --search doesn't use regular expressions now anymore by default, so
+  emerge --search dvd+rw-tools now works as expected. Regular expressions can be enabled
+  by prefixing the search string with %. 
+* emerge --depclean algorithm is much safer than the old one.
+* emerge --newuse detects changes in IUSE that previously went undetected.
+
+portage-2.1
+==================================
+
+* new cache framework, breaking all old cache modules.
+  If you're having problems with portage_db_cdb, this is likely the cause.
+* USE flag output ordering has changed.  The old ordering is now an option
+  by the name of --alphabetical.  Adding the option to EMERGE_DEFAULT_OPTS
+  in make.conf will restore the old behaviour permanently.
+* The deprecated --inject has been removed, use /etc/portage/profile/package.provided
+* The deprecated --upgradeonly has been removed, use /etc/portage/package.* 
+  instead.
+* 'emerge sync' has been deprecated, use 'emerge --sync' instead (same 
+  for other actions)
+* Tools that call emerge should override the EMERGE_DEFAULT_OPTS environment
+  variable or use the emerge --ignore-default-opts option.
+* rsync option handling has been redesigned, instead of RSYNC_* variables
+  use PORTAGE_RSYNC_EXTRA_OPTS from now on.
+* autouse (use.defaults) has been deprecated by specifying USE_ORDER in make.defaults
+  Users may still turn this back on by specifying USE_ORDER="env:pkg:conf:auto:defaults"
+  in make.conf.  Interested in figuring out what use flags were turned off?  Check out
+  /usr/portage/profiles/base/use.defaults and other use.defaults files that correspond 
+  to your profile.
+
Index: /vendor/portage/current/TEST-NOTES
===================================================================
--- /vendor/portage/current/TEST-NOTES	(revision 3419)
+++ /vendor/portage/current/TEST-NOTES	(revision 3419)
@@ -0,0 +1,27 @@
+UnitTests
+---------
+
+Portage has some tests that use the unittest framework that ships with python (2.3-2.4ish)
+Tests have a specific naming convention.
+
+in tests/ there is a runTest script that invokes tests/__init__.py
+
+This init looks at a hardcoded list of test dirs to search for tests.
+If you add a new dir and don't see your new tests, make sure that the dir is in this list.
+
+On the subject of adding more directories; the layout is basically 1 directory per portage
+file at this point (we have few files, and even fewer large files).  Inside of the dir
+you should have files of the form test_${function}.py.
+
+So if I was to write a vercmp test, and vercmp is in portage_versions.
+
+tests/portage_versions/test_vercmp.py
+
+would be the filename.
+
+The __init__.py file now does recursive tests, but you need to tell it so.  For example, if
+you had cache tests the dir format would be something like...
+
+tests/cache/flat_hash/test_foo.py
+
+and you would put "cache/flat_hash" into the testDirs variable in __init__.py.
Index: /vendor/portage/current/bin/archive-conf
===================================================================
--- /vendor/portage/current/bin/archive-conf	(revision 3419)
+++ /vendor/portage/current/bin/archive-conf	(revision 3419)
@@ -0,0 +1,108 @@
+#!/usr/bin/python
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: archive-conf 5597 2007-01-12 08:19:46Z antarus $
+
+#
+# archive-conf -- save off a config file in the dispatch-conf archive dir
+#
+#  Written by Wayne Davison <gentoo@blorf.net> with code snagged from
+#  Jeremy Wohl's dispatch-conf script and the portage chkcontents script.
+#
+
+import os, sys
+try:
+    import portage
+except ImportError:
+    from os import path as osp
+    sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
+    import portage
+
+import dispatch_conf
+
+FIND_EXTANT_CONTENTS  = "find %s -name CONTENTS"
+
+MANDATORY_OPTS  = [ 'archive-dir' ]
+
+try:
+    import fchksum
+    def perform_checksum(filename): return fchksum.fmd5t(filename)
+except ImportError:
+    import md5
+    def md5_to_hex(md5sum):
+        hexform = ""
+        for ix in xrange(len(md5sum)):
+            hexform = hexform + "%02x" % ord(md5sum[ix])
+        return hexform.lower()
+    
+    def perform_checksum(filename):
+        f = open(filename, 'rb')
+        blocksize=32768
+        data = f.read(blocksize)
+        size = 0L
+        sum = md5.new()
+        while data:
+            sum.update(data)
+            size = size + len(data)
+            data = f.read(blocksize)
+        return (md5_to_hex(sum.digest()),size)
+
+def archive_conf():
+    args = []
+    content_files = []
+    md5_match_hash = {}
+
+    options = dispatch_conf.read_config(MANDATORY_OPTS)
+
+    for conf in sys.argv[1:]:
+        if not os.path.isabs(conf):
+            conf = os.path.abspath(conf)
+        args += [ conf ]
+        md5_match_hash[conf] = ''
+
+    # Find all the CONTENT files in VDB_PATH.
+    content_files += os.popen(FIND_EXTANT_CONTENTS % (portage.root+portage.VDB_PATH)).readlines()
+
+    # Search for the saved md5 checksum of all the specified config files
+    # and see if the current file is unmodified or not.
+    try:
+        todo_cnt = len(args)
+        for file in content_files:
+            file = file.rstrip()
+            try:
+                contents = open(file, "r")
+            except IOError, e:
+                print >> sys.stderr, 'archive-conf: Unable to open %s: %s' % (file, e)
+                sys.exit(1)
+            lines = contents.readlines()
+            for line in lines:
+                items = line.split()
+                if items[0] == 'obj':
+                    for conf in args:
+                        if items[1] == conf:
+                            stored = items[2].lower()
+                            real = perform_checksum(conf)[0].lower()
+                            if stored == real:
+                                md5_match_hash[conf] = conf
+                            todo_cnt -= 1
+                            if todo_cnt == 0:
+                                raise "Break"
+    except "Break":
+        pass
+
+    for conf in args:
+        archive = os.path.join(options['archive-dir'], conf.lstrip('/'))
+        if options['use-rcs'] == 'yes':
+            dispatch_conf.rcs_archive(archive, conf, md5_match_hash[conf], '')
+            if md5_match_hash[conf]:
+                dispatch_conf.rcs_archive_post_process(archive)
+        else:
+            dispatch_conf.file_archive(archive, conf, md5_match_hash[conf], '')
+            if md5_match_hash[conf]:
+                dispatch_conf.file_archive_post_process(archive)
+
+# run
+if len(sys.argv) > 1:
+    archive_conf()
+else:
+    print >> sys.stderr, 'Usage: archive-conf /CONFIG/FILE [/CONFIG/FILE...]'
Index: /vendor/portage/current/bin/check-implicit-pointer-usage.py
===================================================================
--- /vendor/portage/current/bin/check-implicit-pointer-usage.py	(revision 3419)
+++ /vendor/portage/current/bin/check-implicit-pointer-usage.py	(revision 3419)
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+
+# Ripped from HP and updated from Debian
+# Update by Gentoo to support unicode output
+
+#
+# Copyright (c) 2004 Hewlett-Packard Development Company, L.P.
+#	David Mosberger <davidm@hpl.hp.com>
+#
+# Scan standard input for GCC warning messages that are likely to
+# source of real 64-bit problems.  In particular, see whether there
+# are any implicitly declared functions whose return values are later
+# interpreted as pointers.  Those are almost guaranteed to cause
+# crashes.
+#
+import re
+import sys
+
+implicit_pattern = re.compile("([^:]*):(\d+): warning: implicit declaration "
+                              + "of function `([^']*)'")
+pointer_pattern = re.compile(
+    "([^:]*):(\d+): warning: "
+    + "("
+    +  "(assignment"
+    +  "|initialization"
+    +  "|return"
+    +  "|passing arg \d+ of `[^']*'"
+    +  "|passing arg \d+ of pointer to function"
+    +  ") makes pointer from integer without a cast"
+    + "|"
+    + "cast to pointer from integer of different size)")
+last_implicit_filename = ""
+last_implicit_linenum = -1
+last_implicit_func = ""
+
+while True:
+    line = sys.stdin.readline()
+    if line == '':
+        break
+    # translate unicode open/close quotes to ascii ones
+    line = line.replace("\xE2\x80\x98", "`").replace("\xE2\x80\x99", "'")
+    m = implicit_pattern.match(line)
+    if m:
+        last_implicit_filename = m.group(1)
+        last_implicit_linenum = int(m.group(2))
+        last_implicit_func = m.group(3)
+    else:
+        m = pointer_pattern.match(line)
+        if m:
+            pointer_filename = m.group(1)
+            pointer_linenum = int(m.group(2))
+            if (last_implicit_filename == pointer_filename
+                and last_implicit_linenum == pointer_linenum):
+                print "Function `%s' implicitly converted to pointer at " \
+                      "%s:%d" % (last_implicit_func, last_implicit_filename,
+                                 last_implicit_linenum)
Index: /vendor/portage/current/bin/chkcontents
===================================================================
--- /vendor/portage/current/bin/chkcontents	(revision 3419)
+++ /vendor/portage/current/bin/chkcontents	(revision 3419)
@@ -0,0 +1,66 @@
+#!/usr/bin/python
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: chkcontents 5597 2007-01-12 08:19:46Z antarus $
+
+# Very simple program to compare the md5sums of a package as listed
+# in VDB_PATH/category/package/CONTENTS with the md5sums of the
+# actual programs on the system (and makes sure that symlinks point to
+# the right files).
+
+import os.path, os, sys
+try:
+	import portage
+except ImportError:
+	from os import path as osp
+	sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
+	import portage
+
+def CONTENTScheck(path):
+	try:
+		contents = open(path, "r")
+	except IOError, e:
+		print "Unable to open %s: %s" % (path, e)
+		sys.exit(1)
+	lines = contents.readlines()
+	for line in lines:
+		items = line.split()
+		# items is a list w/ size depending on the type of item listed in item[0]
+		# if items[0] = 'dir' then items[1] is the path of a directory
+		# if items[0] = 'obj' then items[1] is the path of a file,
+		#                          items[2] is the file's md5sum,
+		#                          items[3] is the file's size
+		# if items[0] = 'sym' then items[1] is the path of a symbolic link,
+		#                          items[2] is '->'
+		#                          items[3] is the file the symlink should point to
+		#                          items[4] is the symlink mtime 
+		if (items[0] == 'obj'):
+			md5stored = items[2].lower()
+			# fchksum.fmdft(file) returns the file's md5sum and the file's size
+			md5real = portage.perform_checksum(items[1])[0].lower()
+			if (md5stored != md5real):
+				if md5real:
+					print "%s has md5sum of %s instead of %s" % (items[1], md5real, md5stored)
+				else:
+					print "%s is missing!" % items[1]
+		elif (items[0] == 'sym'):
+			link = items[1]
+			target = items[3]
+			if (not os.path.islink(link)):
+				print "%s is not a symbolic link" % link
+				continue
+			actualtarget = os.readlink(link)
+			if (os.path.normpath(actualtarget) != os.path.normpath(target)):
+				print "%s points to %s, not %s" % (link, actualtarget, target)
+
+
+if __name__ == '__main__':
+	import sys
+	if (len(sys.argv) != 2 or sys.argv[1] == "--help"):
+		print "This program compares md5sums in the file VDB_PATH/category/package/CONTENTS"
+		print "with the md5sums of the actual files on the filesystem"
+		print "(and makes sure that symlinks point to the right files)."
+		print "\nUsage: chkcontents path/to/CONTENTS"
+		sys.exit(1)
+	CONTENTScheck(sys.argv[1])
+
Index: /vendor/portage/current/bin/clean_locks
===================================================================
--- /vendor/portage/current/bin/clean_locks	(revision 3419)
+++ /vendor/portage/current/bin/clean_locks	(revision 3419)
@@ -0,0 +1,44 @@
+#!/usr/bin/python -O
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: clean_locks 4884 2006-10-31 04:23:06Z zmedico $
+
+import os,sys,errno
+try:
+	import portage_locks
+except ImportError:
+	from os import path as osp
+	sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
+	import portage_locks
+
+if not sys.argv[1:] or "--help" in sys.argv or "-h" in sys.argv:
+	import portage
+	print
+	print "You must specify directories with hardlink-locks to clean."
+	print "You may optionally specify --force, which will remove all"
+	print "of the locks, even if we can't establish if they are in use."
+	print "Please attempt cleaning without force first."
+	print
+	print "%s %s/.locks" % (sys.argv[0], portage.settings["DISTDIR"])
+	print "%s --force %s/.locks" % (sys.argv[0], portage.settings["DISTDIR"])
+	print
+	sys.exit(1)
+	
+force = False
+if "--force" in sys.argv[1:]:
+	force=True
+	
+for x in sys.argv[1:]:
+	if x == "--force":
+		continue
+	try:
+		for y in portage_locks.hardlock_cleanup(x, remove_all_locks=force):
+			print y
+		print
+		
+	except OSError, e:
+		if e.errno in (errno.ENOENT, errno.ENOTDIR):
+			print "!!! %s is not a directory or does not exist" % x
+		else:
+			raise
+		sys.exit(e.errno)
Index: /vendor/portage/current/bin/dispatch-conf
===================================================================
--- /vendor/portage/current/bin/dispatch-conf	(revision 3419)
+++ /vendor/portage/current/bin/dispatch-conf	(revision 3419)
@@ -0,0 +1,368 @@
+#!/usr/bin/python -O
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: dispatch-conf 5605 2007-01-12 09:57:16Z zmedico $
+
+#
+# dispatch-conf -- Integrate modified configs, post-emerge
+#
+#  Jeremy Wohl (http://igmus.org)
+#
+# TODO
+#  dialog menus
+#
+
+if not hasattr(__builtins__, "set"):
+	from sets import Set as set
+
+from stat import *
+from random import *
+import atexit, commands, os, re, shutil, stat, sys
+try:
+    import portage
+except ImportError:
+    from os import path as osp
+    sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
+    import portage
+
+import dispatch_conf
+from portage_exec import find_binary
+
+FIND_EXTANT_CONFIGS  = "find '%s' %s -iname '._cfg????_%s' ! -iname '.*~' ! -iname '.*.bak'"
+DIFF_CONTENTS        = 'diff -Nu %s %s'
+DIFF_CVS_INTERP      = 'diff -Nu %s %s | grep "^[+-][^+-]" | grep -v "# .Header:.*"'
+DIFF_WSCOMMENTS      = 'diff -Nu %s %s | grep "^[+-][^+-]" | grep -v "^[-+]#" | grep -v "^[-+][:space:]*$"'
+
+# We need a secure scratch dir and python does silly verbose errors on the use of tempnam
+oldmask = os.umask(0077)
+SCRATCH_DIR = None
+while SCRATCH_DIR is None:
+    try:
+        mydir = "/tmp/dispatch-conf."
+        for x in range(0,8):
+            if int(random() * 3) == 0:
+                mydir += chr(int(65+random()*26.0))
+            elif int(random() * 2) == 0:
+                mydir += chr(int(97+random()*26.0))
+            else:
+                mydir += chr(int(48+random()*10.0))
+        if os.path.exists(mydir):
+            continue
+        os.mkdir(mydir)
+        SCRATCH_DIR = mydir
+    except OSError, e:
+        if e.errno != 17:
+            raise
+os.umask(oldmask)
+
+# Ensure the scratch dir is deleted
+def cleanup(mydir=SCRATCH_DIR):
+    shutil.rmtree(mydir)
+atexit.register(cleanup)
+
+MANDATORY_OPTS  = [ 'archive-dir', 'diff', 'replace-cvs', 'replace-wscomments', 'merge' ]
+
+class dispatch:
+    options = {}
+
+    def grind (self, config_paths):
+        confs = []
+        count = 0
+
+
+        self.options = dispatch_conf.read_config(MANDATORY_OPTS)
+
+        if self.options.has_key("log-file"):
+            if os.path.isfile(self.options["log-file"]):
+                shutil.copy(self.options["log-file"], self.options["log-file"] + '.old')
+            if os.path.isfile(self.options["log-file"]) \
+               or not os.path.exists(self.options["log-file"]):
+                open(self.options["log-file"], 'w').close() # Truncate it
+                os.chmod(self.options["log-file"], 0600)
+        else:
+            self.options["log-file"] = "/dev/null"
+
+        #
+        # Build list of extant configs
+        #
+
+        for path in config_paths.split ():
+            path = portage.normalize_path(path)
+            try:
+                mymode = os.stat(path).st_mode
+            except OSError:
+                continue
+            basename = "*"
+            find_opts = ""
+            if not stat.S_ISDIR(mymode):
+                path, basename = os.path.split(path)
+                find_opts = "-maxdepth 1"
+
+            confs += self.massage(os.popen(FIND_EXTANT_CONFIGS % (path, find_opts, basename)).readlines())
+
+        if self.options['use-rcs'] == 'yes':
+            for rcs_util in ("rcs", "ci", "co", "rcsmerge"):
+                if not find_binary(rcs_util):
+                    print >> sys.stderr, \
+                        'dispatch-conf: Error finding all RCS utils and " + \
+                        "use-rcs=yes in config; fatal'
+                    return False
+
+
+        # config file freezing support
+        frozen_files = set(self.options.get("frozen-files", "").split())
+        auto_zapped = []
+
+        #
+        # Remove new configs identical to current
+        #                  and
+        # Auto-replace configs a) whose differences are simply CVS interpolations,
+        #                  or  b) whose differences are simply ws or comments,
+        #                  or  c) in paths now unprotected by CONFIG_PROTECT_MASK,
+        #
+
+        def f (conf):
+            mrgconf = re.sub(r'\._cfg', '._mrg', conf['new'])
+            archive = os.path.join(self.options['archive-dir'], conf['current'].lstrip('/'))
+            if self.options['use-rcs'] == 'yes':
+                mrgfail = dispatch_conf.rcs_archive(archive, conf['current'], conf['new'], mrgconf)
+            else:
+                mrgfail = dispatch_conf.file_archive(archive, conf['current'], conf['new'], mrgconf)
+            if os.path.exists(archive + '.dist'):
+                unmodified = len(commands.getoutput(DIFF_CONTENTS % (conf['current'], archive + '.dist'))) == 0
+            else:
+                unmodified = 0
+            if os.path.exists(mrgconf):
+                if mrgfail or len(commands.getoutput(DIFF_CONTENTS % (conf['new'], mrgconf))) == 0:
+                    os.unlink(mrgconf)
+                    newconf = conf['new']
+                else:
+                    newconf = mrgconf
+            else:
+                newconf = conf['new']
+
+            mystatus, myoutput = commands.getstatusoutput(
+                DIFF_CONTENTS  % (conf ['current'], newconf))
+            same_file = 0 == len(myoutput)
+            if mystatus >> 8 == 2:
+                # Binary files differ
+                same_cvs = False
+                same_wsc = False
+            else:
+                same_cvs = 0 == len(commands.getoutput(
+                    DIFF_CVS_INTERP % (conf ['current'], newconf)))
+                same_wsc = 0 == len(commands.getoutput(
+                    DIFF_WSCOMMENTS % (conf ['current'], newconf)))
+
+            # Do options permit?
+            same_cvs = same_cvs and self.options['replace-cvs'] == 'yes'
+            same_wsc = same_wsc and self.options['replace-wscomments'] == 'yes'
+            unmodified = unmodified and self.options['replace-unmodified'] == 'yes'
+
+            if same_file:
+                os.unlink (conf ['new'])
+                self.post_process(conf['current'])
+                if os.path.exists(mrgconf):
+                    os.unlink(mrgconf)
+                return False
+            elif conf['current'] in frozen_files:
+                """Frozen files are automatically zapped. The new config has
+                already been archived with a .new suffix.  When zapped, it is
+                left with the .new suffix (post_process is skipped), since it
+                hasn't been merged into the current config."""
+                auto_zapped.append(conf['current'])
+                os.unlink(conf['new'])
+                try:
+                    os.unlink(mrgconf)
+                except OSError:
+                    pass
+                return False
+            elif unmodified or same_cvs or same_wsc or conf ['dir'] in portage.settings ['CONFIG_PROTECT_MASK'].split ():
+                self.replace(newconf, conf['current'])
+                self.post_process(conf['current'])
+                if newconf == mrgconf:
+                    os.unlink(conf['new'])
+                elif os.path.exists(mrgconf):
+                    os.unlink(mrgconf)
+                return False
+            else:
+                return True
+
+        confs = filter (f, confs)
+
+        #
+        # Interactively process remaining
+        #
+
+        for conf in confs:
+            count = count + 1
+
+            newconf = conf['new']
+            mrgconf = re.sub(r'\._cfg', '._mrg', newconf)
+            if os.path.exists(mrgconf):
+                newconf = mrgconf
+            show_new_diff = 0
+
+            while 1:
+                if show_new_diff:
+                    os.system((self.options['diff']) % (conf['new'], mrgconf))
+                    show_new_diff = 0
+                else:
+                    os.system((self.options['diff']) % (conf['current'], newconf))
+
+                print
+                print '>> (%i of %i) -- %s' % (count, len(confs), conf ['current'])
+                print '>> q quit, h help, n next, e edit-new, z zap-new, u use-new\n   m merge, t toggle-merge, l look-merge: ',
+
+                c = getch ()
+
+                if c == 'q':
+                    sys.exit (0)
+                if c == 'h':
+                    self.do_help ()
+                    continue
+                elif c == 't':
+                    if newconf == mrgconf:
+                        newconf = conf['new']
+                    elif os.path.exists(mrgconf):
+                        newconf = mrgconf
+                    continue
+                elif c == 'n':
+                    break
+                elif c == 'm':
+                    merged = SCRATCH_DIR+"/"+os.path.basename(conf['current'])
+                    print
+                    ret = os.system (self.options['merge'] % (merged, conf ['current'], newconf))
+                    if ret:
+                        print "Failure running 'merge' command"
+                        continue
+                    shutil.copyfile(merged, mrgconf)
+                    os.remove(merged)
+                    mystat = os.lstat(conf['new'])
+                    os.chmod(mrgconf, mystat[ST_MODE])
+                    os.chown(mrgconf, mystat[ST_UID], mystat[ST_GID])
+                    newconf = mrgconf
+                    continue
+                elif c == 'l':
+                    show_new_diff = 1
+                    continue
+                elif c == 'e':
+                    if not os.environ.has_key('EDITOR'):
+                        os.environ['EDITOR']='nano'
+                    os.system(os.environ['EDITOR'] + ' ' + newconf)
+                    continue
+                elif c == 'z':
+                    os.unlink(conf['new'])
+                    if os.path.exists(mrgconf):
+                        os.unlink(mrgconf)
+                    break
+                elif c == 'u':
+                    self.replace(newconf, conf ['current'])
+                    self.post_process(conf['current'])
+                    if newconf == mrgconf:
+                        os.unlink(conf['new'])
+                    elif os.path.exists(mrgconf):
+                        os.unlink(mrgconf)
+                    break
+                else:
+                    continue
+
+        if auto_zapped:
+            print
+            print " One or more updates are frozen and have been automatically zapped:"
+            print
+            for frozen in auto_zapped:
+                print "  * '%s'" % frozen
+            print
+
+    def replace (self, newconf, curconf):
+        """Replace current config with the new/merged version.  Also logs
+        the diff of what changed into the configured log file."""
+        os.system((DIFF_CONTENTS % (curconf, newconf)) + '>>' + self.options["log-file"])
+        try:
+            os.rename(newconf, curconf)
+        except (IOError, os.error), why:
+            print >> sys.stderr, 'dispatch-conf: Error renaming %s to %s: %s; fatal' % \
+                  (newconf, curconf, str(why))
+
+
+    def post_process(self, curconf):
+        archive = os.path.join(self.options['archive-dir'], curconf.lstrip('/'))
+        if self.options['use-rcs'] == 'yes':
+            dispatch_conf.rcs_archive_post_process(archive)
+        else:
+            dispatch_conf.file_archive_post_process(archive)
+
+
+    def massage (self, newconfigs):
+        """Sort, rstrip, remove old versions, break into triad hash.
+
+        Triad is dictionary of current (/etc/make.conf), new (/etc/._cfg0003_make.conf)
+        and dir (/etc).
+
+        We keep ._cfg0002_conf over ._cfg0001_conf and ._cfg0000_conf.
+        """
+        h = {}
+
+        newconfigs.sort ()
+
+        for nconf in newconfigs:
+            nconf = nconf.rstrip ()
+            conf  = re.sub (r'\._cfg\d+_', '', nconf)
+            dir   = re.match (r'^(.+)/', nconf).group (1)
+
+            if h.has_key (conf):
+                mrgconf = re.sub(r'\._cfg', '._mrg', h[conf]['new'])
+                if os.path.exists(mrgconf):
+                    os.unlink(mrgconf)
+                os.unlink(h[conf]['new'])
+
+            h [conf] = { 'current' : conf, 'dir' : dir, 'new' : nconf }
+
+        configs = h.values ()
+        configs.sort (lambda a, b: cmp(a ['current'], b ['current']))
+
+        return configs
+
+
+    def do_help (self):
+        print; print
+
+        print '  u -- update current config with new config and continue'
+        print '  z -- zap (delete) new config and continue'
+        print '  n -- skip to next config, leave all intact'
+        print '  e -- edit new config'
+        print '  m -- interactively merge current and new configs'
+        print '  l -- look at diff between pre-merged and merged configs'
+        print '  t -- toggle new config between merged and pre-merged state'
+        print '  h -- this screen'
+        print '  q -- quit'
+
+        print; print 'press any key to return to diff...',
+
+        getch ()
+
+
+def getch ():
+    # from ASPN - Danny Yoo
+    #
+    import sys, tty, termios
+
+    fd = sys.stdin.fileno()
+    old_settings = termios.tcgetattr(fd)
+    try:
+        tty.setraw(sys.stdin.fileno())
+        ch = sys.stdin.read(1)
+    finally:
+        termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
+    return ch
+
+
+# run
+d = dispatch ()
+
+if len(sys.argv) > 1:
+    # for testing
+    d.grind (" ".join(sys.argv[1:]))
+else:
+    d.grind (portage.settings ['CONFIG_PROTECT'])
Index: /vendor/portage/current/bin/dobin
===================================================================
--- /vendor/portage/current/bin/dobin	(revision 3419)
+++ /vendor/portage/current/bin/dobin	(revision 3419)
@@ -0,0 +1,27 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: dobin 3483 2006-06-10 21:40:40Z genone $
+
+if [[ $# -lt 1 ]] ; then
+	echo "$0: at least one argument needed" 1>&2
+	exit 1
+fi
+
+if [[ ! -d ${D}${DESTTREE}/bin ]] ; then
+	install -d "${D}${DESTTREE}/bin" || exit 2
+fi
+
+ret=0
+
+for x in "$@" ; do
+	if [[ -e ${x} ]] ; then
+		install -m0755 -o ${PORTAGE_INST_UID:-0} -g ${PORTAGE_INST_GID:-0} "${x}" "${D}${DESTTREE}/bin"
+	else
+		echo "!!! ${0##*/}: ${x} does not exist" 1>&2
+		false
+	fi
+	((ret+=$?))
+done
+
+exit ${ret}
Index: /vendor/portage/current/bin/doconfd
===================================================================
--- /vendor/portage/current/bin/doconfd	(revision 3419)
+++ /vendor/portage/current/bin/doconfd	(revision 3419)
@@ -0,0 +1,14 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: doconfd 3483 2006-06-10 21:40:40Z genone $
+
+if [[ $# -lt 1 ]] ; then
+	echo "$0: at least one argument needed" 1>&2
+	exit 1
+fi
+
+exec \
+env \
+INSDESTTREE="/etc/conf.d/" \
+doins "$@"
Index: /vendor/portage/current/bin/dodir
===================================================================
--- /vendor/portage/current/bin/dodir	(revision 3419)
+++ /vendor/portage/current/bin/dodir	(revision 3419)
@@ -0,0 +1,7 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: dodir 3483 2006-06-10 21:40:40Z genone $
+
+slash=/
+exec install -d ${DIROPTIONS} "${@/#${slash}/${D}${slash}}"
Index: /vendor/portage/current/bin/dodoc
===================================================================
--- /vendor/portage/current/bin/dodoc	(revision 3419)
+++ /vendor/portage/current/bin/dodoc	(revision 3419)
@@ -0,0 +1,27 @@
+#!/bin/bash
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: dodoc 5555 2007-01-11 18:50:51Z vapier $
+
+if [ $# -lt 1 ] ; then
+	vecho "${0##*/}: at least one argument needed" 1>&2
+	exit 1 	
+fi
+
+dir="${D}usr/share/doc/${PF}/${DOCDESTTREE}"
+if [ ! -d "${dir}" ] ; then
+	install -d "${dir}"
+fi
+
+ret=0
+for x in "$@" ; do
+	if [ -s "${x}" ] ; then
+		install -m0644 "${x}" "${dir}"
+		ecompress "${dir}/${x##*/}"
+	elif [ ! -e "${x}" ] ; then
+		echo "dodoc: ${x} does not exist" 1>&2
+		((++ret))
+	fi
+done
+
+exit ${ret}
Index: /vendor/portage/current/bin/doenvd
===================================================================
--- /vendor/portage/current/bin/doenvd	(revision 3419)
+++ /vendor/portage/current/bin/doenvd	(revision 3419)
@@ -0,0 +1,14 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: doenvd 3483 2006-06-10 21:40:40Z genone $
+
+if [[ $# -lt 1 ]] ; then
+	echo "$0: at least one argument needed" 1>&2
+	exit 1
+fi
+
+exec \
+env \
+INSDESTTREE="/etc/env.d/" \
+doins "$@"
Index: /vendor/portage/current/bin/doexe
===================================================================
--- /vendor/portage/current/bin/doexe	(revision 3419)
+++ /vendor/portage/current/bin/doexe	(revision 3419)
@@ -0,0 +1,28 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: doexe 3483 2006-06-10 21:40:40Z genone $
+
+source "${PORTAGE_BIN_PATH:-/usr/lib/portage/bin}"/isolated-functions.sh
+
+if [[ $# -lt 1 ]] ; then
+	echo "$0: at least one argument needed" 1>&2
+	exit 1
+fi
+
+if [[ ! -d ${D}${EXEDESTTREE} ]] ; then
+	install -d "${D}${EXEDESTTREE}"
+fi
+
+for x in "$@" ; do
+	if [ -L "${x}" ] ; then
+		cp "${x}" "${T}"
+		mysrc="${T}"/$(/usr/bin/basename "${x}")
+	elif [ -d "${x}" ] ; then
+		vecho "doexe: warning, skipping directory ${x}"
+		continue
+	else
+		mysrc="${x}"
+	fi
+	install ${EXEOPTIONS} "${mysrc}" "${D}${EXEDESTTREE}"
+done
Index: /vendor/portage/current/bin/dohard
===================================================================
--- /vendor/portage/current/bin/dohard	(revision 3419)
+++ /vendor/portage/current/bin/dohard	(revision 3419)
@@ -0,0 +1,14 @@
+#!/bin/bash
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: dohard 3483 2006-06-10 21:40:40Z genone $
+
+if [[ $# -ne 2 ]] ; then
+	echo "$0: two arguments needed" 1>&2
+	exit 1
+fi
+
+destdir=${2%/*}
+[[ ! -d ${D}${destdir} ]] && dodir "${destdir}"
+
+exec ln -f "${D}$1" "${D}$2"
Index: /vendor/portage/current/bin/dohard.orig
===================================================================
--- /vendor/portage/current/bin/dohard.orig	(revision 3419)
+++ /vendor/portage/current/bin/dohard.orig	(revision 3419)
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: dohard 3483 2006-06-10 21:40:40Z genone $
+
+if [[ $# -ne 2 ]] ; then
+	echo "$0: two arguments needed" 1>&2
+	exit 1
+fi
+
+target=$1
+linkname=$2
+exec ln -f "${D}${target}" "${D}${linkname}"
Index: /vendor/portage/current/bin/dohtml
===================================================================
--- /vendor/portage/current/bin/dohtml	(revision 3419)
+++ /vendor/portage/current/bin/dohtml	(revision 3419)
@@ -0,0 +1,172 @@
+#!/usr/bin/python
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: dohtml 5642 2007-01-14 05:06:51Z zmedico $
+
+#
+# Typical usage:
+# dohtml -r docs/*
+#  - put all files and directories in docs into /usr/share/doc/${PF}/html
+# dohtml foo.html
+#  - put foo.html into /usr/share/doc/${PF}/html
+#
+#
+# Detailed usage:
+# dohtml <list-of-files> 
+#  - will install the files in the list of files (space-separated list) into 
+#    /usr/share/doc/${PF}/html, provided the file ends in .html, .png, .jpg 
+#     or .css
+# dohtml -r <list-of-files-and-directories>
+#  - will do as 'dohtml', but recurse into all directories, as long as the 
+#    directory name is not CVS
+# dohtml -A jpe,java [-r] <list-of-files[-and-directories]>
+#  - will do as 'dohtml' but add .jpe,.java (default filter list is
+#    added to your list)
+# dohtml -a png,gif,html,htm [-r] <list-of-files[-and-directories]>
+#  - will do as 'dohtml' but filter on .png,.gif,.html,.htm (default filter 
+#    list is ignored)
+# dohtml -x CVS,SCCS,RCS -r <list-of-files-and-directories>
+#  - will do as 'dohtml -r', but ignore directories named CVS, SCCS, RCS
+#
+
+import os
+import sys
+import types
+
+def dodir(path):
+	os.system("install -d '%s'" % path)
+
+def dofile(src,dst):
+
+	os.system("install -m0644 '%s' '%s'" % (src, dst))
+
+def install(basename, dirname, options, prefix=""):
+
+	fullpath = basename
+	if prefix: fullpath = prefix + "/" + fullpath
+	if dirname: fullpath = dirname + "/" + fullpath
+
+	if options.DOCDESTTREE:
+		destdir = options.D + "usr/share/doc/" + options.PF + "/" + options.DOCDESTTREE + "/" + options.doc_prefix + "/" + prefix
+	else:
+		destdir = options.D + "usr/share/doc/" + options.PF + "/html/" + options.doc_prefix + "/" + prefix
+
+	if os.path.isfile(fullpath):
+		ext = os.path.splitext(basename)[1]
+		if (len(ext) and ext[1:] in options.allowed_exts) or basename in options.allowed_files:
+			dodir(destdir)
+			dofile(fullpath, destdir + "/" + basename)
+	elif options.recurse and os.path.isdir(fullpath) and \
+	     basename not in options.disallowed_dirs:
+		for i in os.listdir(fullpath):
+			pfx = basename
+			if prefix: pfx = prefix + "/" + pfx
+			install(i, dirname, options, pfx)
+	else:
+		return False
+	return True
+
+
+class OptionsClass:
+	def __init__(self):
+		self.PF = ""
+		self.D = ""
+		self.DOCDESTTREE = ""
+		
+		if os.environ.has_key("PF"):
+			self.PF = os.environ["PF"]
+		if os.environ.has_key("D"):
+			self.D = os.environ["D"]
+		if os.environ.has_key("DOCDESTTREE"):
+			self.DOCDESTTREE = os.environ["DOCDESTTREE"]
+		
+		self.allowed_exts = [ 'png', 'gif', 'html', 'htm', 'jpg', 'css', 'js' ]
+		self.allowed_files = []
+		self.disallowed_dirs = [ 'CVS' ]
+		self.recurse = False
+		self.verbose = False
+		self.doc_prefix = ""
+
+def print_help():
+	opts = OptionsClass()
+
+	print "dohtml [-a .foo,.bar] [-A .foo,.bar] [-f foo,bar] [-x foo,bar]"
+	print "       [-r] [-V] <file> [file ...]"
+	print
+	print " -a   Set the list of allowed to those that are specified."
+	print "      Default:", ",".join(opts.allowed_exts)
+	print " -A   Extend the list of allowed file types."
+	print " -f   Set list of allowed extensionless file names."
+	print " -x   Set directories to be excluded from recursion."
+	print "      Default:", ",".join(opts.disallowed_dirs)
+	print " -r   Install files and directories recursively."
+	print " -V   Be verbose."
+	print
+
+def parse_args():
+	options = OptionsClass()
+	args = []
+	
+	x = 1
+	while x < len(sys.argv):
+		arg = sys.argv[x]
+		if arg in ["-h","-r","-V"]:
+			if arg == "-h":
+				print_help()
+				sys.exit(0)
+			elif arg == "-r":
+				options.recurse = True
+			elif arg == "-V":
+				options.verbose = True
+		elif sys.argv[x] in ["-A","-a","-f","-x","-p"]:
+			x += 1
+			if x == len(sys.argv):
+				print_help()
+				sys.exit(0)
+			elif arg == "-p":
+				options.doc_prefix = sys.argv[x]
+			else:
+				values = sys.argv[x].split(",")
+				if arg == "-A":
+					options.allowed_exts.extend(values)
+				elif arg == "-a":
+					options.allowed_exts = values
+				elif arg == "-f":
+					options.allowed_files = values
+				elif arg == "-x":
+					options.disallowed_dirs = values
+		else:
+			args.append(sys.argv[x])
+		x += 1
+	
+	return (options, args)
+
+def main():
+
+	(options, args) = parse_args()
+
+	if type(options.allowed_exts) == types.StringType:
+		options.allowed_exts = options.allowed_exts.split(",")
+
+	if options.verbose:
+		print "Allowed extensions:", options.allowed_exts
+		print "Document prefix : '" + options.doc_prefix	 + "'"
+		print "Allowed files :", options.allowed_files
+
+	success = True
+	
+	for x in args:
+		basename = os.path.basename(x)
+		dirname  = os.path.dirname(x)
+		if not install(basename, dirname, options):
+			success = False
+	
+	if success:
+		retcode = 0
+	else:
+		retcode = 1
+	
+	sys.exit(retcode)
+
+if __name__ == "__main__":
+	main()
Index: /vendor/portage/current/bin/doinfo
===================================================================
--- /vendor/portage/current/bin/doinfo	(revision 3419)
+++ /vendor/portage/current/bin/doinfo	(revision 3419)
@@ -0,0 +1,15 @@
+#!/bin/bash
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: doinfo 5555 2007-01-11 18:50:51Z vapier $
+
+if [[ -z $1 ]] ; then
+	vecho "${0##*/}: at least one argument needed"
+	exit 1 	
+fi
+
+if [[ ! -d ${D}usr/share/info ]] ; then
+	install -d "${D}usr/share/info" || exit 1
+fi
+
+exec install -m0644 "$@" "${D}usr/share/info"
Index: /vendor/portage/current/bin/doinitd
===================================================================
--- /vendor/portage/current/bin/doinitd	(revision 3419)
+++ /vendor/portage/current/bin/doinitd	(revision 3419)
@@ -0,0 +1,14 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: doinitd 3483 2006-06-10 21:40:40Z genone $
+
+if [[ $# -lt 1 ]] ; then
+	echo "$0: at least one argument needed" 1>&2
+	exit 1
+fi
+
+exec \
+env \
+EXEDESTTREE="/etc/init.d/" \
+doexe "$@"
Index: /vendor/portage/current/bin/doins
===================================================================
--- /vendor/portage/current/bin/doins	(revision 3419)
+++ /vendor/portage/current/bin/doins	(revision 3419)
@@ -0,0 +1,55 @@
+#!/bin/bash
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: doins 3483 2006-06-10 21:40:40Z genone $
+
+source "${PORTAGE_BIN_PATH:-/usr/lib/portage/bin}"/isolated-functions.sh
+
+if [ $# -lt 1 ] ; then
+	echo "${0##*/}: at least one argument needed" 1>&2
+	exit 1
+fi
+
+if [[ "$1" == "-r" ]] ; then
+	DOINSRECUR=y
+	shift
+else
+	DOINSRECUR=n
+fi
+[[ -z ${INSDEPTH} ]] && declare -i INSDEPTH=0
+if [[ ${INSDEPTH} -gt 30 ]] ; then
+	echo "${0##*/}: sanity check ... 30 directories is too much :(" 2>&1
+	exit 1
+fi
+
+if [[ ${INSDESTTREE#${D}} != "${INSDESTTREE}" ]]; then
+	vecho "-------------------------------------------------------" 1>&2
+	vecho "You should not use \${D} with helpers." 1>&2
+	vecho "  --> ${INSDESTTREE}" 1>&2
+	vecho "-------------------------------------------------------" 1>&2
+	exit 1
+fi
+
+[[ ! -d ${D}${INSDESTTREE} ]] && dodir "${INSDESTTREE}"
+
+for x in "$@" ; do
+	if [ -L "$x" ] ; then
+		cp "$x" "${T}"
+		mysrc="${T}/$(/usr/bin/basename "${x}")"
+	elif [ -d "$x" ] ; then
+		if [ "${DOINSRECUR}" == "n" ] ; then
+			continue
+		fi
+
+		mydir="${INSDESTTREE}/$(basename "${x}")"
+		find "${x}" -mindepth 1 -maxdepth 1 -exec \
+			env \
+				INSDESTTREE="${mydir}" \
+				INSDEPTH=$((INSDEPTH+1)) \
+				doins -r {} \;
+		continue
+	else
+		mysrc="${x}"
+	fi
+	install ${INSOPTIONS} "${mysrc}" "${D}${INSDESTTREE}"
+done
Index: /vendor/portage/current/bin/dolib
===================================================================
--- /vendor/portage/current/bin/dolib	(revision 3419)
+++ /vendor/portage/current/bin/dolib	(revision 3419)
@@ -0,0 +1,41 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: dolib 3483 2006-06-10 21:40:40Z genone $
+
+# Setup ABI cruft
+LIBDIR_VAR="LIBDIR_${ABI}"
+if [[ -n ${ABI} && -n ${!LIBDIR_VAR} ]] ; then
+	CONF_LIBDIR=${!LIBDIR_VAR}
+fi
+unset LIBDIR_VAR
+# we need this to default to lib so that things dont break
+CONF_LIBDIR=${CONF_LIBDIR:-lib}
+libdir="${D}${DESTTREE}/${CONF_LIBDIR}"
+
+
+if [[ $# -lt 1 ]] ; then
+	echo "$0: at least one argument needed" 1>&2
+	exit 1
+fi
+if [[ ! -d ${libdir} ]] ; then
+	install -d "${libdir}" || exit 1
+fi
+
+ret=0
+
+for x in "$@" ; do
+	if [[ -e ${x} ]] ; then
+		if [[ ! -L ${x} ]] ; then
+			install ${LIBOPTIONS} "${x}" "${libdir}"
+		else
+			ln -s "$(readlink "${x}")" "${libdir}/${x##*/}"
+		fi
+	else
+		echo "!!! ${0##*/}: ${x} does not exist" 1>&2
+		false
+	fi
+	((ret+=$?))
+done
+
+exit ${ret}
Index: /vendor/portage/current/bin/doman
===================================================================
--- /vendor/portage/current/bin/doman	(revision 3419)
+++ /vendor/portage/current/bin/doman	(revision 3419)
@@ -0,0 +1,54 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: doman 5507 2007-01-10 04:22:27Z zmedico $
+
+source "${PORTAGE_BIN_PATH:-/usr/lib/portage/bin}"/isolated-functions.sh
+
+if [[ $# -lt 1 ]] ; then
+	echo "$0: at least one argument needed" 1>&2
+	exit 1
+fi
+
+i18n=""
+
+ret=0
+
+for x in "$@" ; do
+	if [[ ${x:0:6} == "-i18n=" ]] ; then
+		i18n=${x:6}/
+		continue
+	fi
+	if [[ ${x:0:6} == ".keep_" ]] ; then
+		continue
+	fi
+
+	suffix=${x##*.}
+
+	# These will be automatically decompressed by ecompressdir.
+	if hasq ${suffix} Z gz bz2 ; then
+		realname=${x%.*}
+		suffix=${realname##*.}
+	fi
+
+	mandir=${i18n}man${suffix:0:1}
+
+	if echo ${mandir} | egrep -q 'man[0-9n](|f|p|pm)$' -; then
+		if [[ -s ${x} ]] ; then
+			if [[ ! -d ${D}/usr/share/man/${mandir} ]] ; then
+				install -d "${D}/usr/share/man/${mandir}"
+			fi
+
+			install -m0644 "${x}" "${D}/usr/share/man/${mandir}"
+			((ret+=$?))
+		elif [[ ! -e ${x} ]] ; then
+			vecho "doman: ${x} does not exist" 1>&2
+			((++ret))
+		fi
+	else
+		vecho "doman: '${x}' is probably not a man page; skipping" 1>&2
+		((++ret))
+	fi
+done
+
+exit ${ret}
Index: /vendor/portage/current/bin/domo
===================================================================
--- /vendor/portage/current/bin/domo	(revision 3419)
+++ /vendor/portage/current/bin/domo	(revision 3419)
@@ -0,0 +1,26 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: domo 3483 2006-06-10 21:40:40Z genone $
+
+mynum=${#}
+if [ ${mynum} -lt 1 ] ; then
+	echo "${0}: at least one argument needed"
+	exit 1
+fi
+if [ ! -d "${D}${DESTTREE}/share/locale" ] ; then
+	install -d "${D}${DESTTREE}/share/locale/"
+fi
+
+for x in "$@" ; do
+	if [ -e "${x}" ] ; then
+		mytiny="${x##*/}"
+		mydir="${D}${DESTTREE}/share/locale/${mytiny%.*}/LC_MESSAGES"
+		if [ ! -d "${mydir}" ] ; then
+			install -d "${mydir}"
+		fi
+		install -m0644 "${x}" "${mydir}/${MOPREFIX}.mo"
+	else
+		echo "${0}: ${x} does not exist"
+	fi
+done
Index: /vendor/portage/current/bin/dosbin
===================================================================
--- /vendor/portage/current/bin/dosbin	(revision 3419)
+++ /vendor/portage/current/bin/dosbin	(revision 3419)
@@ -0,0 +1,27 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: dosbin 3483 2006-06-10 21:40:40Z genone $
+
+if [[ $# -lt 1 ]] ; then
+	echo "$0: at least one argument needed" 1>&2
+	exit 1
+fi
+
+if [[ ! -d ${D}${DESTTREE}/sbin ]] ; then
+	install -d "${D}${DESTTREE}/sbin" || exit 2
+fi
+
+ret=0
+
+for x in "$@" ; do
+	if [[ -e ${x} ]] ; then
+		install -m0755 -o ${PORTAGE_INST_UID:-0} -g ${PORTAGE_INST_GID:-0} "${x}" "${D}${DESTTREE}/sbin"
+	else
+		echo "!!! ${0##*/}: ${x} does not exist" 1>&2
+		false
+	fi
+	((ret+=$?))
+done
+
+exit ${ret}
Index: /vendor/portage/current/bin/dosed
===================================================================
--- /vendor/portage/current/bin/dosed	(revision 3419)
+++ /vendor/portage/current/bin/dosed	(revision 3419)
@@ -0,0 +1,20 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: dosed 4763 2006-10-20 07:39:49Z zmedico $
+
+mysed="s:${D}::g"
+
+for x in "$@" ; do
+	y="${D}${x}"
+	if [ -e "${y}" ] ; then
+		if [ -f "${y}" ] ; then
+			sed -i -e "${mysed}" "${y}"
+		else
+			echo "${y} is not a regular file!"
+			exit 1
+		fi
+	else
+		mysed="${x}"
+	fi
+done
Index: /vendor/portage/current/bin/dosym
===================================================================
--- /vendor/portage/current/bin/dosym	(revision 3419)
+++ /vendor/portage/current/bin/dosym	(revision 3419)
@@ -0,0 +1,14 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: dosym 3483 2006-06-10 21:40:40Z genone $
+
+if [[ $# -ne 2 ]] ; then
+	echo "$0: two arguments needed" 1>&2
+	exit 1
+fi
+
+destdir=${2%/*}
+[[ ! -d ${D}${destdir} ]] && dodir "${destdir}"
+
+exec ln -snf "$1" "${D}$2"
Index: /vendor/portage/current/bin/ebuild
===================================================================
--- /vendor/portage/current/bin/ebuild	(revision 3419)
+++ /vendor/portage/current/bin/ebuild	(revision 3419)
@@ -0,0 +1,150 @@
+#!/usr/bin/python -O
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-src/portage/bin/ebuild,v 1.18.2.3 2005/05/07 04:32:59 ferringb Exp $
+
+import getopt, os, sys
+
+if len(sys.argv) <= 2:
+	print "Usage: ebuild <ebuild file> <command> [command] ..."
+	print ""
+	print "See the ebuild(1) man page for more info"
+	sys.exit(1)
+
+
+opts, pargs = getopt.getopt(sys.argv[1:], '', ['debug', 'force'])
+debug = ("--debug",'') in opts
+force = ("--force",'') in opts
+
+if "merge" in pargs:
+	print "Disabling noauto in features... merge disables it. (qmerge doesn't)"
+	os.environ["FEATURES"] = os.environ.get("FEATURES", "") + " -noauto"
+
+os.environ["PORTAGE_CALLER"]="ebuild"
+try:
+	import portage
+except ImportError:
+	from os import path as osp
+	sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
+	import portage
+
+import portage_util, portage_const
+import portage_dep
+portage_dep._dep_check_strict = True
+
+# do this _after_ 'import portage' to prevent unnecessary tracing
+if debug and "python-trace" in portage.features:
+	import portage_debug
+	portage_debug.set_trace(True)
+
+if portage.settings["NOCOLOR"] in ("yes","true") or not sys.stdout.isatty():
+	import output
+	output.nocolor()
+
+ebuild = pargs.pop(0)
+if not os.path.isabs(ebuild):
+	mycwd = os.getcwd()
+	# Try to get the non-canonical path from the PWD evironment variable, since
+	# the canonical path returned from os.getcwd() may may be unusable in
+	# cases where the directory stucture is built from symlinks.
+	if "PWD" in os.environ and os.environ["PWD"] != mycwd and \
+		os.path.realpath(os.environ["PWD"]) == mycwd:
+		mycwd = portage.normalize_path(os.environ["PWD"])
+	ebuild = os.path.join(mycwd, ebuild)
+ebuild = portage.normalize_path(ebuild)
+# portdbapi uses the canonical path for the base of the portage tree, but
+# subdirectories of the base can be built from symlinks (like crossdev does).
+ebuild_portdir = os.path.realpath(os.path.dirname(os.path.dirname(ebuild)))
+ebuild = os.path.join(ebuild_portdir, *ebuild.split(os.path.sep)[-2:])
+
+if not os.path.exists(ebuild):
+	print "'%s' does not exist." % ebuild
+	sys.exit(1)
+
+ebuild_split = ebuild.split("/")
+del ebuild_split[-2]
+cpv = "/".join(ebuild_split[-2:])[:-7]
+
+if not portage.catpkgsplit(cpv):
+	print "!!! %s does not follow correct package syntax." % (cpv)
+	sys.exit(1)
+
+if ebuild.startswith(portage.root + portage_const.VDB_PATH):
+	mytree = "vartree"
+
+	portage_ebuild = portage.db[portage.root][mytree].dbapi.findname(cpv)
+
+	if os.path.realpath(portage_ebuild) != ebuild:
+		print "!!! Portage seems to think that %s is at %s" % (cpv, portage_ebuild)
+		sys.exit(1)
+
+else:
+	mytree = "porttree"
+
+	portage_ebuild = portage.portdb.findname(cpv)
+
+	if not portage_ebuild or portage_ebuild != ebuild:
+		overlay = "/".join(ebuild_split[:-2])
+		os.environ["PORTDIR_OVERLAY"] = os.environ.get("PORTDIR_OVERLAY","") + " " + overlay
+		print "Appending %s to PORTDIR_OVERLAY..." % overlay
+		portage.close_portdbapi_caches()
+		reload(portage)
+		portage_ebuild = portage.portdb.findname(cpv)
+
+		if not portage_ebuild or portage_ebuild != ebuild:
+			print "!!! %s does not seem to have a valid PORTDIR structure." % overlay
+			sys.exit(1)
+
+
+if len(pargs) > 1 and "config" in pargs:
+	print "config must be called on it's own, not combined with any other phase"
+	sys.exit(1)
+
+def discard_digests(myebuild, mysettings, mydbapi):
+	"""Discard all distfiles digests for the given ebuild.  This is useful when
+	upstream has changed the identity of the distfiles and the user would
+	otherwise have to manually remove the Manifest and files/digest-* files in
+	order to ensure correct results."""
+	try:
+		portage._doebuild_manifest_exempt_depend += 1
+		pkgdir = os.path.dirname(myebuild)
+		fetchlist_dict = portage.FetchlistDict(pkgdir, mysettings, mydbapi)
+		cat, pkg = pkgdir.split(os.sep)[-2:]
+		cpv = cat + "/" + os.path.basename(myebuild)[:-7]
+		from portage_manifest import Manifest
+		mf = Manifest(pkgdir, mysettings["DISTDIR"],
+			fetchlist_dict=fetchlist_dict)
+		mf.create(requiredDistfiles=None,
+			assumeDistHashesSometimes=True, assumeDistHashesAlways=True)
+		distfiles = fetchlist_dict[cpv]
+		for myfile in distfiles:
+			try:
+				del mf.fhashdict["DIST"][myfile]
+			except KeyError:
+				pass
+		mf.write()
+	finally:
+		portage._doebuild_manifest_exempt_depend -= 1
+
+for arg in pargs:
+	try:
+		tmpsettings = portage.config(clone=portage.settings)
+		if arg == "test" and not "test" in tmpsettings.features:
+			print "Forcing test."
+			tmpsettings["EBUILD_FORCE_TEST"] = "1"
+			tmpsettings.backupenv["EBUILD_FORCE_TEST"] = "1"
+		if arg == "digest" and force:
+			discard_digests(ebuild, tmpsettings, portage.portdb)
+		a = portage.doebuild(ebuild, arg, portage.root, tmpsettings,
+			debug=debug, tree=mytree)
+	except KeyboardInterrupt:
+		print "Interrupted."
+		a = 1
+	except KeyError:
+		# aux_get error
+		a = 1
+	if a == None:
+		print "Could not run the required binary?"
+		a = 127
+	if a:
+		sys.exit(a)
Index: /vendor/portage/current/bin/ebuild.sh
===================================================================
--- /vendor/portage/current/bin/ebuild.sh	(revision 3419)
+++ /vendor/portage/current/bin/ebuild.sh	(revision 3419)
@@ -0,0 +1,1704 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: ebuild.sh 5646 2007-01-14 21:56:00Z zmedico $
+
+PORTAGE_BIN_PATH="${PORTAGE_BIN_PATH:-/usr/lib/portage/bin}"
+PORTAGE_PYM_PATH="${PORTAGE_PYM_PATH:-/usr/lib/portage/pym}"
+declare -rx PORTAGE_BIN_PATH PORTAGE_PYM_PATH
+
+SANDBOX_PREDICT="${SANDBOX_PREDICT}:/proc/self/maps:/dev/console:/dev/random"
+export SANDBOX_PREDICT="${SANDBOX_PREDICT}:${PORTAGE_PYM_PATH}:${PORTAGE_DEPCACHEDIR}"
+export SANDBOX_WRITE="${SANDBOX_WRITE}:/dev/shm:/dev/stdout:/dev/stderr:${PORTAGE_TMPDIR}"
+export SANDBOX_READ="${SANDBOX_READ}:/dev/shm:/dev/stdin:${PORTAGE_TMPDIR}"
+
+if [ ! -z "${PORTAGE_GPG_DIR}" ]; then
+	SANDBOX_PREDICT="${SANDBOX_PREDICT}:${PORTAGE_GPG_DIR}"
+fi
+
+declare -rx EBUILD_PHASE
+
+if [ "$*" != "depend" ] && [ "$*" != "clean" ] && [ "$*" != "nofetch" ]; then
+	if [ -f "${T}/environment" ]; then
+		source "${T}/environment" >& /dev/null
+	fi
+fi
+
+# These two functions wrap sourcing and calling respectively.  At present they
+# perform a qa check to make sure eclasses and ebuilds and profiles don't mess
+# with shell opts (shopts).  Ebuilds/eclasses changing shopts should reset them 
+# when they are done.  Note:  For now these shoudl always return success.
+
+qa_source() {
+	local shopts=$(shopt) OLDIFS="$IFS"
+	source "$@" || return 1
+	[[ $shopts != $(shopt) ]] &&
+		eqawarn "QA Notice: Global shell options changed and were not restored while sourcing '$*'"
+	[[ "$IFS" != "$OLDIFS" ]] &&
+		eqawarn "QA Notice: Global IFS changed and was not restored while sourcing '$*'"
+	return 0
+}
+
+qa_call() {
+	local shopts=$(shopt) OLDIFS="$IFS"
+	"$@" || return 1
+	[[ $shopts != $(shopt) ]] &&
+		eqawarn "QA Notice: Global shell options changed and were not restored while calling '$*'"
+	[[ "$IFS" != "$OLDIFS" ]] &&
+		eqawarn "QA Notice: Global IFS changed and was not restored while calling '$*'"
+	return 0
+}
+
+# subshell die support
+EBUILD_MASTER_PID=$$
+trap 'exit 1' SIGTERM
+
+EBUILD_SH_ARGS="$*"
+
+shift $#
+
+# Prevent aliases from causing portage to act inappropriately.
+# Make sure it's before everything so we don't mess aliases that follow.
+unalias -a
+
+# Unset some variables that break things.
+unset GZIP BZIP BZIP2 CDPATH GREP_OPTIONS GREP_COLOR GLOBIGNORE
+
+# We need this next line for "die" and "assert". It expands
+# It _must_ preceed all the calls to die and assert.
+shopt -s expand_aliases
+alias die='diefunc "$FUNCNAME" "$LINENO" "$?"'
+alias assert='_pipestatus="${PIPESTATUS[*]}"; [[ "${_pipestatus// /}" -eq 0 ]] || diefunc "$FUNCNAME" "$LINENO" "$_pipestatus"'
+alias save_IFS='[ "${IFS:-unset}" != "unset" ] && old_IFS="${IFS}"'
+alias restore_IFS='if [ "${old_IFS:-unset}" != "unset" ]; then IFS="${old_IFS}"; unset old_IFS; else unset IFS; fi'
+
+OCC="$CC"
+OCXX="$CXX"
+
+export PATH="/usr/local/sbin:/sbin:/usr/sbin:${PORTAGE_BIN_PATH}:/usr/local/bin:/bin:/usr/bin:${ROOTPATH}"
+[ ! -z "$PREROOTPATH" ] && export PATH="${PREROOTPATH%%:}:$PATH"
+
+source "${PORTAGE_BIN_PATH}/isolated-functions.sh"  &>/dev/null
+
+[[ $PORTAGE_QUIET != "" ]] && export PORTAGE_QUIET
+
+# the sandbox is disabled by default except when overridden in the relevant stages
+export SANDBOX_ON="0"
+
+# sandbox support functions; defined prior to profile.bashrc srcing, since the profile might need to add a default exception (/usr/lib64/conftest fex)
+addread() {
+	[[ -z $1 || -n $2 ]] && die "Usage: addread <colon-delimited list of paths>"
+	export SANDBOX_READ="$SANDBOX_READ:$1"
+}
+
+addwrite() {
+	[[ -z $1 || -n $2 ]] && die "Usage: addwrite <colon-delimited list of paths>"
+	export SANDBOX_WRITE="$SANDBOX_WRITE:$1"
+}
+
+adddeny() {
+	[[ -z $1 || -n $2 ]] && die "Usage: adddeny <colon-delimited list of paths>"
+	export SANDBOX_DENY="$SANDBOX_DENY:$1"
+}
+
+addpredict() {
+	[[ -z $1 || -n $2 ]] && die "Usage: addpredict <colon-delimited list of paths>"
+	export SANDBOX_PREDICT="$SANDBOX_PREDICT:$1"
+}
+
+lchown() {
+	chown -h "$@"
+}
+
+lchgrp() {
+	chgrp -h "$@"
+}
+
+# source the existing profile.bashrc's.
+save_IFS
+IFS=$'\n'
+for dir in ${PROFILE_PATHS}; do
+	# Must unset it so that it doesn't mess up assumptions in the RCs.
+	unset IFS
+	if [ -f "${dir}/profile.bashrc" ]; then
+		qa_source "${dir}/profile.bashrc"
+	fi
+done
+restore_IFS
+
+# We assume if people are changing shopts in their bashrc they do so at their
+# own peril.  This is the ONLY non-portage bit of code that can change shopts
+# without a QA violation.
+if [ -f "${PORTAGE_BASHRC}" ]; then
+	# If $- contains x, then tracing has already enabled elsewhere for some
+	# reason.  We preserve it's state so as not to interfere.
+	if [ "$PORTAGE_DEBUG" != "1" ] || [ "${-/x/}" != "$-" ]; then
+		source "${PORTAGE_BASHRC}"
+	else
+		set -x
+		source "${PORTAGE_BASHRC}"
+		set +x
+	fi
+fi
+
+[ ! -z "$OCC" ] && export CC="$OCC"
+[ ! -z "$OCXX" ] && export CXX="$OCXX"
+
+esyslog() {
+	# Custom version of esyslog() to take care of the "Red Star" bug.
+	# MUST follow functions.sh to override the "" parameter problem.
+	return 0
+}
+
+use() {
+	useq ${1}
+}
+
+usev() {
+	if useq ${1}; then
+		echo "${1}"
+		return 0
+	fi
+	return 1
+}
+
+useq() {
+	local u=$1
+	local found=0
+
+	# if we got something like '!flag', then invert the return value
+	if [[ ${u:0:1} == "!" ]] ; then
+		u=${u:1}
+		found=1
+	fi
+
+	# Make sure we have this USE flag in IUSE
+	if ! hasq "${u}" ${IUSE} ${E_IUSE} && ! hasq "${u}" ${PORTAGE_ARCHLIST} selinux; then
+		eqawarn "QA Notice: USE Flag '${u}' not in IUSE for ${CATEGORY}/${PF}"
+	fi
+
+	if hasq ${u} ${USE} ; then
+		return ${found}
+	else
+		return $((!found))
+	fi
+}
+
+has_version() {
+	if [ "${EBUILD_PHASE}" == "depend" ]; then
+		die "portageq calls (has_version calls portageq) are not allowed in the global scope"
+	fi
+	# return shell-true/shell-false if exists.
+	# Takes single depend-type atoms.
+	if "${PORTAGE_BIN_PATH}/portageq" 'has_version' "${ROOT}" "$1"; then
+		return 0
+	else
+		return 1
+	fi
+}
+
+portageq() {
+	if [ "${EBUILD_PHASE}" == "depend" ]; then
+		die "portageq calls are not allowed in the global scope"
+	fi
+	"${PORTAGE_BIN_PATH}/portageq" "$@"
+}
+
+
+# ----------------------------------------------------------------------------
+# ----------------------------------------------------------------------------
+# ----------------------------------------------------------------------------
+
+
+best_version() {
+	if [ "${EBUILD_PHASE}" == "depend" ]; then
+		die "portageq calls (best_version calls portageq) are not allowed in the global scope"
+	fi
+	# returns the best/most-current match.
+	# Takes single depend-type atoms.
+	"${PORTAGE_BIN_PATH}/portageq" 'best_version' "${ROOT}" "$1"
+}
+
+use_with() {
+	if [ -z "$1" ]; then
+		echo "!!! use_with() called without a parameter." >&2
+		echo "!!! use_with <USEFLAG> [<flagname> [value]]" >&2
+		return 1
+	fi
+
+	local UW_SUFFIX=""
+	if [ ! -z "${3}" ]; then
+		UW_SUFFIX="=${3}"
+	fi
+
+	local UWORD="$2"
+	if [ -z "${UWORD}" ]; then
+		UWORD="$1"
+	fi
+
+	if useq $1; then
+		echo "--with-${UWORD}${UW_SUFFIX}"
+	else
+		echo "--without-${UWORD}"
+	fi
+	return 0
+}
+
+use_enable() {
+	if [ -z "$1" ]; then
+		echo "!!! use_enable() called without a parameter." >&2
+		echo "!!! use_enable <USEFLAG> [<flagname> [value]]" >&2
+		return 1
+	fi
+
+	local UE_SUFFIX=""
+	if [ ! -z "${3}" ]; then
+		UE_SUFFIX="=${3}"
+	fi
+
+	local UWORD="$2"
+	if [ -z "${UWORD}" ]; then
+		UWORD="$1"
+	fi
+
+	if useq $1; then
+		echo "--enable-${UWORD}${UE_SUFFIX}"
+	else
+		echo "--disable-${UWORD}"
+	fi
+	return 0
+}
+
+register_die_hook() {
+	export EBUILD_DEATH_HOOKS="${EBUILD_DEATH_HOOKS} $*"
+}
+
+diefunc() {
+	local funcname="$1" lineno="$2" exitcode="$3"
+	shift 3
+	echo >&2
+	echo "!!! ERROR: $CATEGORY/$PF failed." >&2
+	dump_trace 2 1>&2
+	echo "  $(basename "${BASH_SOURCE[1]}"), line ${BASH_LINENO[0]}:   Called die" 1>&2
+	echo >&2
+	echo "!!! ${*:-(no error message)}" >&2
+	echo "!!! If you need support, post the topmost build error, and the call stack if relevant." >&2
+	[ -n "${PORTAGE_LOG_FILE}" ] && \
+		echo "!!! A complete build log is located at '${PORTAGE_LOG_FILE}'." >&2
+	echo >&2
+	if [ -n "${EBUILD_OVERLAY_ECLASSES}" ] ; then
+		echo "This ebuild used the following eclasses from overlays:" >&2
+		echo >&2
+		for x in ${EBUILD_OVERLAY_ECLASSES} ; do
+			echo "  ${x}" >&2
+		done
+		echo >&2
+	fi
+
+	if [ "${EBUILD_PHASE/depend}" == "${EBUILD_PHASE}" ]; then
+		local x
+		for x in $EBUILD_DEATH_HOOKS; do
+			${x} "$@" >&2 1>&2
+		done
+	fi
+
+	# subshell die support
+	kill -s SIGTERM ${EBUILD_MASTER_PID}
+	exit 1
+}
+
+shopt -s extdebug &> /dev/null
+
+# usage- first arg is the number of funcs on the stack to ignore.
+# defaults to 1 (ignoring dump_trace)
+dump_trace() {
+	local funcname="" sourcefile="" lineno="" n e s="yes"
+
+	declare -i strip=1
+
+	if [[ -n $1 ]]; then
+		strip=$(( $1 ))
+	fi
+	
+	echo "Call stack:"
+	for (( n = ${#FUNCNAME[@]} - 1, p = ${#BASH_ARGV[@]} ; n > $strip ; n-- )) ; do
+		funcname=${FUNCNAME[${n} - 1]}
+		sourcefile=$(basename ${BASH_SOURCE[${n}]})
+		lineno=${BASH_LINENO[${n} - 1]}
+		# Display function arguments
+		args=
+		if [[ -n "${BASH_ARGV[@]}" ]]; then
+			for (( j = 1 ; j <= ${BASH_ARGC[${n} - 1]} ; ++j )); do
+				newarg=${BASH_ARGV[$(( p - j - 1 ))]}
+				args="${args:+${args} }'${newarg}'"
+			done
+			(( p -= ${BASH_ARGC[${n} - 1]} ))
+		fi
+		echo "  ${sourcefile}, line ${lineno}:   Called ${funcname}${args:+ ${args}}"
+	done
+}
+
+
+
+#if no perms are specified, dirs/files will have decent defaults
+#(not secretive, but not stupid)
+umask 022
+export DESTTREE=/usr
+export INSDESTTREE=""
+export EXEDESTTREE=""
+export DOCDESTTREE=""
+export INSOPTIONS="-m0644"
+export EXEOPTIONS="-m0755"
+export LIBOPTIONS="-m0644"
+export DIROPTIONS="-m0755"
+export MOPREFIX=${PN}
+
+check_KV() {
+	if [ -z "${KV}" ]; then
+		eerror ""
+		eerror "Could not determine your kernel version."
+		eerror "Make sure that you have a /usr/src/linux symlink,"
+		eerror "and that the indicated kernel has been configured."
+		eerror "You can also simply run the following command"
+		eerror "in the directory referenced by /usr/src/linux:"
+		eerror " make include/linux/version.h"
+		eerror ""
+		die
+	fi
+}
+
+# adds ".keep" files so that dirs aren't auto-cleaned
+keepdir() {
+	dodir "$@"
+	local x
+	if [ "$1" == "-R" ] || [ "$1" == "-r" ]; then
+		shift
+		find "$@" -type d -printf "${D}/%p/.keep_${CATEGORY}_${PN}-${SLOT}\n" | tr "\n" "\0" | $XARGS -0 -n100 touch || die "Failed to recursively create .keep files"
+	else
+		for x in "$@"; do
+			touch "${D}/${x}/.keep_${CATEGORY}_${PN}-${SLOT}" || die "Failed to create .keep in ${D}/${x}"
+		done
+	fi
+}
+
+unpack() {
+	local x
+	local y
+	local myfail
+	local tar_opts=""
+	[ -z "$*" ] && die "Nothing passed to the 'unpack' command"
+
+	for x in "$@"; do
+		vecho ">>> Unpacking ${x} to ${PWD}"
+		y=${x%.*}
+		y=${y##*.}
+
+		myfail="${x} does not exist"
+		if [ "${x:0:2}" = "./" ] ; then
+			srcdir=""
+		else
+			srcdir="${DISTDIR}/"
+		fi
+		[[ ${x} == ${DISTDIR}* ]] && \
+			die "Arguments to unpack() should not begin with \${DISTDIR}."
+		[ ! -s "${srcdir}${x}" ] && die "$myfail"
+
+		myfail="failure unpacking ${x}"
+		case "${x##*.}" in
+			tar)
+				tar xof "${srcdir}${x}" ${tar_opts} || die "$myfail"
+				;;
+			tgz)
+				tar xozf "${srcdir}${x}" ${tar_opts} || die "$myfail"
+				;;
+			tbz|tbz2)
+				bzip2 -dc "${srcdir}${x}" | tar xof - ${tar_opts}
+				assert "$myfail"
+				;;
+			ZIP|zip|jar)
+				unzip -qo "${srcdir}${x}" || die "$myfail"
+				;;
+			gz|Z|z)
+				if [ "${y}" == "tar" ]; then
+					tar zoxf "${srcdir}${x}" ${tar_opts} || die "$myfail"
+				else
+					gzip -dc "${srcdir}${x}" > ${x%.*} || die "$myfail"
+				fi
+				;;
+			bz2|bz)
+				if [ "${y}" == "tar" ]; then
+					bzip2 -dc "${srcdir}${x}" | tar xof - ${tar_opts}
+					assert "$myfail"
+				else
+					bzip2 -dc "${srcdir}${x}" > ${x%.*} || die "$myfail"
+				fi
+				;;
+			7Z|7z)
+				local my_output
+				my_output="$(7z x -y "${srcdir}/${x}")"
+				if [ $? -ne 0 ]; then
+					echo "${my_output}" >&2
+					die "$myfail"
+				fi
+				;;
+			RAR|rar)
+				unrar x -idq -o+ "${srcdir}/${x}" || die "$myfail"
+				;;
+			LHa|LHA|lha|lzh)
+				lha xqf "${srcdir}/${x}" || die "$myfail"
+				;;
+			a|deb)
+				ar x "${srcdir}/${x}" || die "$myfail"
+				;;
+			*)
+				vecho "unpack ${x}: file format not recognized. Ignoring."
+				;;
+		esac
+	done
+	# Do not chmod '.' since it's probably ${WORKDIR} and PORTAGE_WORKDIR_MODE
+	# should be preserved.
+	find . -mindepth 1 -maxdepth 1 ! -type l -print0 | \
+		${XARGS} -0 chmod -fR a+rX,u+w,g-w,o-w
+}
+
+strip_duplicate_slashes() {
+	if [[ -n $1 ]] ; then
+		local removed=$1
+		while [[ ${removed} == *//* ]] ; do
+			removed=${removed//\/\///}
+		done
+		echo ${removed}
+	fi
+}
+
+econf() {
+	local x
+	local LOCAL_EXTRA_ECONF="${EXTRA_ECONF}"
+
+	if [ -z "${ECONF_SOURCE}" ]; then
+		ECONF_SOURCE="."
+	fi
+	if [ -x "${ECONF_SOURCE}/configure" ]; then
+		if [ -e /usr/share/gnuconfig/ ]; then
+			for x in $(find "${WORKDIR}" -type f '(' -name config.guess -o -name config.sub ')') ; do
+				vecho " * econf: updating ${x/${WORKDIR}\/} with /usr/share/gnuconfig/${x##*/}"
+				cp -f /usr/share/gnuconfig/${x##*/} ${x}
+			done
+		fi
+
+		if [ ! -z "${CBUILD}" ]; then
+			LOCAL_EXTRA_ECONF="--build=${CBUILD} ${LOCAL_EXTRA_ECONF}"
+		fi
+
+		if [ ! -z "${CTARGET}" ]; then
+			LOCAL_EXTRA_ECONF="--target=${CTARGET} ${LOCAL_EXTRA_ECONF}"
+		fi
+
+		# if the profile defines a location to install libs to aside from default, pass it on.
+		# if the ebuild passes in --libdir, they're responsible for the conf_libdir fun.
+		LIBDIR_VAR="LIBDIR_${ABI}"
+		if [ -n "${ABI}" -a -n "${!LIBDIR_VAR}" ]; then
+			CONF_LIBDIR="${!LIBDIR_VAR}"
+		fi
+		unset LIBDIR_VAR
+		if [ -n "${CONF_LIBDIR}" ] && [ "${*/--libdir}" == "$*" ]; then
+			if [ "${*/--exec-prefix}" != "$*" ]; then
+				local args="$(echo $*)"
+				local -a pref=($(echo ${args/*--exec-prefix[= ]}))
+				CONF_PREFIX=${pref}
+				[ "${CONF_PREFIX:0:1}" != "/" ] && CONF_PREFIX="/${CONF_PREFIX}"
+			elif [ "${*/--prefix}" != "$*" ]; then
+				local args="$(echo $*)"
+				local -a pref=($(echo ${args/*--prefix[= ]}))
+				CONF_PREFIX=${pref}
+				[ "${CONF_PREFIX:0:1}" != "/" ] && CONF_PREFIX="/${CONF_PREFIX}"
+			else
+				CONF_PREFIX="/usr"
+			fi
+			export CONF_PREFIX
+			[ "${CONF_LIBDIR:0:1}" != "/" ] && CONF_LIBDIR="/${CONF_LIBDIR}"
+
+			CONF_LIBDIR_RESULT="$(strip_duplicate_slashes ${CONF_PREFIX}${CONF_LIBDIR})"
+
+			LOCAL_EXTRA_ECONF="--libdir=${CONF_LIBDIR_RESULT} ${LOCAL_EXTRA_ECONF}"
+		fi
+
+		local TMP_CONFCACHE_DIR CONFCACHE_ARG
+		if hasq confcache $FEATURES && ! hasq confcache $RESTRICT; then
+			CONFCACHE="$(type -P confcache)"
+			if [ -z "${CONFCACHE}" ]; then
+				ewarn "disabling confcache, binary cannot be found"
+			else
+				CONFCACHE="${CONFCACHE/ /\ }"
+				TMP_CONFCACHE_DIR="${CONFCACHE:+${CONFCACHE_DIR:-${PORTAGE_TMPDIR}/confcache}}"
+				TMP_CONFCACHE_DIR="${TMP_CONFCACHE_DIR/ /\ }"
+				CONFCACHE_ARG="--confcache-dir"
+				local s
+				if [ -n "$CCACHE_DIR" ]; then
+					s="$CCACHE_DIR"
+				fi
+				if [ -n "$DISTCC_DIR" ]; then
+					s="${s:+${s}:}$DISTCC_DIR"
+				fi
+				if [ -n "$s" ]; then
+					CONFCACHE_ARG="--confcache-ignore $s $CONFCACHE_ARG"
+				fi
+			fi
+		else
+			CONFCACHE=
+		fi
+
+		vecho ${CONFCACHE} ${CONFCACHE_ARG} ${TMP_CONFCACHE_DIR} "${ECONF_SOURCE}/configure" \
+			--prefix=/usr \
+			--host=${CHOST} \
+			--mandir=/usr/share/man \
+			--infodir=/usr/share/info \
+			--datadir=/usr/share \
+			--sysconfdir=/etc \
+			--localstatedir=/var/lib \
+			"$@" \
+			${LOCAL_EXTRA_ECONF}
+
+		if ! ${CONFCACHE} ${CONFCACHE_ARG} ${TMP_CONFCACHE_DIR} "${ECONF_SOURCE}/configure" \
+			--prefix=/usr \
+			--host=${CHOST} \
+			--mandir=/usr/share/man \
+			--infodir=/usr/share/info \
+			--datadir=/usr/share \
+			--sysconfdir=/etc \
+			--localstatedir=/var/lib \
+			"$@"  \
+			${LOCAL_EXTRA_ECONF}; then
+
+			if [ -s config.log ]; then
+				echo
+				echo "!!! Please attach the following file when filing a report to bugs.gentoo.org:"
+				echo "!!! ${PWD}/config.log"
+			fi
+			die "econf failed"
+		fi
+	else
+		die "no configure script found"
+	fi
+}
+
+einstall() {
+	# CONF_PREFIX is only set if they didn't pass in libdir above.
+	LIBDIR_VAR="LIBDIR_${ABI}"
+	if [ -n "${ABI}" -a -n "${!LIBDIR_VAR}" ]; then
+		CONF_LIBDIR="${!LIBDIR_VAR}"
+	fi
+	unset LIBDIR_VAR
+	if [ -n "${CONF_LIBDIR}" ] && [ "${CONF_PREFIX:-unset}" != "unset" ]; then
+		EI_DESTLIBDIR="${D}/${CONF_PREFIX}/${CONF_LIBDIR}"
+		EI_DESTLIBDIR="$(strip_duplicate_slashes ${EI_DESTLIBDIR})"
+		EXTRA_EINSTALL="libdir=${EI_DESTLIBDIR} ${EXTRA_EINSTALL}"
+		unset EI_DESTLIBDIR
+	fi
+
+	if [ -f ./[mM]akefile -o -f ./GNUmakefile ] ; then
+		if [ "${PORTAGE_DEBUG}" == "1" ]; then
+			make -n prefix="${D}/usr" \
+				datadir="${D}/usr/share" \
+				infodir="${D}/usr/share/info" \
+				localstatedir="${D}/var/lib" \
+				mandir="${D}/usr/share/man" \
+				sysconfdir="${D}/etc" \
+				${EXTRA_EINSTALL} \
+				"$@" install
+		fi
+		make prefix="${D}/usr" \
+			datadir="${D}/usr/share" \
+			infodir="${D}/usr/share/info" \
+			localstatedir="${D}/var/lib" \
+			mandir="${D}/usr/share/man" \
+			sysconfdir="${D}/etc" \
+			${EXTRA_EINSTALL} \
+			"$@" install || die "einstall failed"
+	else
+		die "no Makefile found"
+	fi
+}
+
+pkg_setup() {
+	return
+}
+
+pkg_nofetch() {
+	[ -z "${SRC_URI}" ] && return
+
+	echo "!!! The following are listed in SRC_URI for ${PN}:"
+	local x
+	for x in $(echo ${SRC_URI}); do
+		echo "!!!   ${x}"
+	done
+}
+
+src_unpack() {
+	[[ -n ${A} ]] && unpack ${A}
+}
+
+src_compile() {
+	if [ -x ./configure ]; then
+		econf
+	fi
+	if [ -f Makefile ] || [ -f GNUmakefile ] || [ -f makefile ]; then
+		emake || die "emake failed"
+	fi
+}
+
+src_test() {
+	if emake -j1 check -n &> /dev/null; then
+		vecho ">>> Test phase [check]: ${CATEGORY}/${PF}"
+		if ! emake -j1 check; then
+			hasq test $FEATURES && die "Make check failed. See above for details."
+			hasq test $FEATURES || eerror "Make check failed. See above for details."
+		fi
+	elif emake -j1 test -n &> /dev/null; then
+		vecho ">>> Test phase [test]: ${CATEGORY}/${PF}"
+		if ! emake -j1 test; then
+			hasq test $FEATURES && die "Make test failed. See above for details."
+			hasq test $FEATURES || eerror "Make test failed. See above for details."
+		fi
+	else
+		vecho ">>> Test phase [none]: ${CATEGORY}/${PF}"
+	fi
+}
+
+src_install() {
+	return
+}
+
+pkg_preinst() {
+	return
+}
+
+pkg_postinst() {
+	return
+}
+
+pkg_prerm() {
+	return
+}
+
+pkg_postrm() {
+	return
+}
+
+pkg_config() {
+	eerror "This ebuild does not have a config function."
+}
+
+# Used to generate the /lib/cpp and /usr/bin/cc wrappers
+gen_wrapper() {
+	cat > "$1" <<-EOF
+	#!/bin/sh
+	exec $2 "\$@"
+	EOF
+	chmod 0755 "$1"
+}
+
+dyn_setup() {
+	[ "$(type -t pre_pkg_setup)" == "function" ] && qa_call pre_pkg_setup
+	qa_call pkg_setup
+	[ "$(type -t post_pkg_setup)" == "function" ] && qa_call post_pkg_setup
+}
+
+dyn_unpack() {
+	[ "$(type -t pre_src_unpack)" == "function" ] && qa_call pre_src_unpack
+	local newstuff="no"
+	if [ -e "${WORKDIR}" ]; then
+		local x
+		local checkme
+		for x in ${AA}; do
+			vecho ">>> Checking ${x}'s mtime..."
+			if [ "${PORTAGE_ACTUAL_DISTDIR:-${DISTDIR}}/${x}" -nt "${WORKDIR}" ]; then
+				vecho ">>> ${x} has been updated; recreating WORKDIR..."
+				newstuff="yes"
+				break
+			fi
+		done
+		if [ "${EBUILD}" -nt "${WORKDIR}" ] && ! hasq keepwork ${FEATURES} ; then
+			vecho ">>> ${EBUILD} has been updated; recreating WORKDIR..."
+			newstuff="yes"
+		elif [ ! -f "${PORTAGE_BUILDDIR}/.unpacked" ]; then
+			vecho ">>> Not marked as unpacked; recreating WORKDIR..."
+			newstuff="yes"
+		fi
+	fi
+	if [ "${newstuff}" == "yes" ]; then
+		# We don't necessarily have privileges to do a full dyn_clean here.
+		rm -rf "${WORKDIR}"
+		if [ -d "${T}" ] && ! hasq keeptemp ${FEATURES} ; then
+			rm -rf "${T}" && mkdir "${T}"
+		else
+			[ -e "${T}/environment" ] && \
+				mv "${T}/environment" "${T}/environment.keeptemp"
+		fi
+	fi
+	if [ -e "${WORKDIR}" ]; then
+		if [ "$newstuff" == "no" ]; then
+			vecho ">>> WORKDIR is up-to-date, keeping..."
+			[ "$(type -t post_src_unpack)" == "function" ] && qa_call post_src_unpack
+			return 0
+		fi
+	fi
+
+	if [ ! -d "${WORKDIR}" ]; then
+		install -m${PORTAGE_WORKDIR_MODE:-0700} -d "${WORKDIR}" || die "Failed to create dir '${WORKDIR}'"
+	fi
+	cd "${WORKDIR}" || die "Directory change failed: \`cd '${WORKDIR}'\`"
+	vecho ">>> Unpacking source..."
+	qa_call src_unpack
+	touch "${PORTAGE_BUILDDIR}/.unpacked" || die "IO Failure -- Failed 'touch .unpacked' in ${PORTAGE_BUILDDIR}"
+	vecho ">>> Source unpacked."
+	cd "${PORTAGE_BUILDDIR}"
+
+	[ "$(type -t post_src_unpack)" == "function" ] && qa_call post_src_unpack
+}
+
+dyn_clean() {
+	if [ -z "${PORTAGE_BUILDDIR}" ]; then
+		echo "Aborting clean phase because PORTAGE_BUILDDIR is unset!"
+		return 1
+	fi
+
+	if type -P chflags > /dev/null ; then
+		chflags -R noschg,nouchg,nosappnd,nouappnd "${PORTAGE_BUILDDIR}"
+		chflags -R nosunlnk,nouunlnk "${PORTAGE_BUILDDIR}" 2>/dev/null
+	fi
+
+	rm -rf "${PORTAGE_BUILDDIR}/image" "${PORTAGE_BUILDDIR}/homedir"
+
+	if ! hasq keeptemp $FEATURES; then
+		rm -rf "${T}"
+	else
+		[ -e "${T}/environment" ] && mv "${T}/environment" "${T}/environment.keeptemp"
+	fi
+
+	if ! hasq keepwork $FEATURES; then
+		rm -rf "${PORTAGE_BUILDDIR}/.logid"
+		rm -rf "${PORTAGE_BUILDDIR}/.unpacked"
+		rm -rf "${PORTAGE_BUILDDIR}/.compiled"
+		rm -rf "${PORTAGE_BUILDDIR}/.tested"
+		rm -rf "${PORTAGE_BUILDDIR}/.installed"
+		rm -rf "${PORTAGE_BUILDDIR}/.packaged"
+		rm -rf "${PORTAGE_BUILDDIR}/build-info"
+		rm -rf "${WORKDIR}"
+	fi
+
+	if [ -f "${PORTAGE_BUILDDIR}/.unpacked" ]; then
+		find "${PORTAGE_BUILDDIR}" -type d ! -regex "^${WORKDIR}" | sort -r | tr "\n" "\0" | $XARGS -0 rmdir &>/dev/null
+	fi
+
+	# do not bind this to doebuild defined DISTDIR; don't trust doebuild, and if mistakes are made it'll
+	# result in it wiping the users distfiles directory (bad).
+	rm -rf "${PORTAGE_BUILDDIR}/distdir"
+
+	if [ -z "$(find "${PORTAGE_BUILDDIR}" -mindepth 1 -maxdepth 1)" ]; then
+		rmdir "${PORTAGE_BUILDDIR}"
+	fi
+
+	true
+}
+
+into() {
+	if [ "$1" == "/" ]; then
+		export DESTTREE=""
+	else
+		export DESTTREE=$1
+		if [ ! -d "${D}${DESTTREE}" ]; then
+			install -d "${D}${DESTTREE}"
+		fi
+	fi
+}
+
+insinto() {
+	if [ "$1" == "/" ]; then
+		export INSDESTTREE=""
+	else
+		export INSDESTTREE=$1
+		if [ ! -d "${D}${INSDESTTREE}" ]; then
+			install -d "${D}${INSDESTTREE}"
+		fi
+	fi
+}
+
+exeinto() {
+	if [ "$1" == "/" ]; then
+		export EXEDESTTREE=""
+	else
+		export EXEDESTTREE="$1"
+		if [ ! -d "${D}${EXEDESTTREE}" ]; then
+			install -d "${D}${EXEDESTTREE}"
+		fi
+	fi
+}
+
+docinto() {
+	if [ "$1" == "/" ]; then
+		export DOCDESTTREE=""
+	else
+		export DOCDESTTREE="$1"
+		if [ ! -d "${D}usr/share/doc/${PF}/${DOCDESTTREE}" ]; then
+			install -d "${D}usr/share/doc/${PF}/${DOCDESTTREE}"
+		fi
+	fi
+}
+
+insopts() {
+	export INSOPTIONS="$@"
+
+	# `install` should never be called with '-s' ...
+	hasq -s ${INSOPTIONS} && die "Never call insopts() with -s"
+}
+
+diropts() {
+	export DIROPTIONS="$@"
+}
+
+exeopts() {
+	export EXEOPTIONS="$@"
+
+	# `install` should never be called with '-s' ...
+	hasq -s ${EXEOPTIONS} && die "Never call exeopts() with -s"
+}
+
+libopts() {
+	export LIBOPTIONS="$@"
+
+	# `install` should never be called with '-s' ...
+	hasq -s ${LIBOPTIONS} && die "Never call libopts() with -s"
+}
+
+abort_handler() {
+	local msg
+	if [ "$2" != "fail" ]; then
+		msg="${EBUILD}: ${1} aborted; exiting."
+	else
+		msg="${EBUILD}: ${1} failed; exiting."
+	fi
+	echo
+	echo "$msg"
+	echo
+	eval ${3}
+	#unset signal handler
+	trap SIGINT SIGQUIT
+}
+
+abort_compile() {
+	abort_handler "src_compile" $1
+	rm -f "${PORTAGE_BUILDDIR}/.compiled"
+	exit 1
+}
+
+abort_test() {
+	abort_handler "dyn_test" $1
+	rm -f "${PORTAGE_BUILDDIR}/.tested"
+	exit 1
+}
+
+abort_install() {
+	abort_handler "src_install" $1
+	rm -rf "${PORTAGE_BUILDDIR}/image"
+	exit 1
+}
+
+dyn_compile() {
+	trap "abort_compile" SIGINT SIGQUIT
+
+	[ "$(type -t pre_src_compile)" == "function" ] && qa_call pre_src_compile
+
+	[ "${CFLAGS-unset}"      != "unset" ] && export CFLAGS
+	[ "${CXXFLAGS-unset}"    != "unset" ] && export CXXFLAGS
+	[ "${LIBCFLAGS-unset}"   != "unset" ] && export LIBCFLAGS
+	[ "${LIBCXXFLAGS-unset}" != "unset" ] && export LIBCXXFLAGS
+	[ "${LDFLAGS-unset}"     != "unset" ] && export LDFLAGS
+	[ "${ASFLAGS-unset}"     != "unset" ] && export ASFLAGS
+
+	[ "${CCACHE_DIR-unset}"  != "unset" ] && export CCACHE_DIR
+	[ "${CCACHE_SIZE-unset}" != "unset" ] && export CCACHE_SIZE
+
+	[ "${DISTCC_DIR-unset}"  == "unset" ] && export DISTCC_DIR="${PORTAGE_TMPDIR}/.distcc"
+	[ ! -z "${DISTCC_DIR}" ] && addwrite "${DISTCC_DIR}"
+
+	LIBDIR_VAR="LIBDIR_${ABI}"
+	if [ -z "${PKG_CONFIG_PATH}" -a -n "${ABI}" -a -n "${!LIBDIR_VAR}" ]; then
+		export PKG_CONFIG_PATH="/usr/${!LIBDIR_VAR}/pkgconfig"
+	fi
+	unset LIBDIR_VAR
+
+	if hasq noauto $FEATURES && [ ! -f ${PORTAGE_BUILDDIR}/.unpacked ]; then
+		echo
+		echo "!!! We apparently haven't unpacked... This is probably not what you"
+		echo "!!! want to be doing... You are using FEATURES=noauto so I'll assume"
+		echo "!!! that you know what you are doing... You have 5 seconds to abort..."
+		echo
+
+		local x
+		for x in 1 2 3 4 5 6 7 8; do
+			echo -ne "\a"
+			LC_ALL=C sleep 0.25
+		done
+
+		sleep 3
+	fi
+
+	local srcdir=${PORTAGE_BUILDDIR}
+	cd "${PORTAGE_BUILDDIR}"
+	if [ ! -e "build-info" ]; then
+		mkdir build-info
+	fi
+	cp "${EBUILD}" "build-info/${PF}.ebuild"
+
+	if [[ ${PORTAGE_BUILDDIR}/.compiled -nt ${WORKDIR} ]] ; then
+		vecho ">>> It appears that '${PF}' is already compiled; skipping."
+		vecho ">>> Remove '${PORTAGE_BUILDDIR}/.compiled' to force compilation."
+		trap SIGINT SIGQUIT
+		[ "$(type -t post_src_compile)" == "function" ] && qa_call post_src_compile
+		return
+	fi
+	if [ -d "${S}" ]; then
+		srcdir=${S}
+		cd "${S}"
+	fi
+	#our custom version of libtool uses $S and $D to fix
+	#invalid paths in .la files
+	export S D
+	#some packages use an alternative to $S to build in, cause
+	#our libtool to create problematic .la files
+	export PWORKDIR="$WORKDIR"
+	vecho ">>> Compiling source in ${srcdir} ..."
+	qa_call src_compile
+	vecho ">>> Source compiled."
+	#|| abort_compile "fail"
+	cd "${PORTAGE_BUILDDIR}"
+	touch .compiled
+	cd build-info
+
+	set -f
+	for f in ASFLAGS CATEGORY CBUILD CC CFLAGS CHOST CTARGET CXX \
+		CXXFLAGS DEPEND EXTRA_ECONF EXTRA_EINSTALL EXTRA_MAKE \
+		FEATURES INHERITED IUSE LDFLAGS LIBCFLAGS LIBCXXFLAGS \
+		LICENSE PDEPEND PF PKGUSE PROVIDE RDEPEND RESTRICT SLOT \
+		KEYWORDS HOMEPAGE SRC_URI DESCRIPTION; do
+		[ -n "${!f}" ] && echo $(echo "${!f}" | tr '\n,\r,\t' ' , , ' | sed s/'  \+'/' '/g) > ${f}
+	done
+	echo "${USE}"		> USE
+	echo "${EAPI:-0}"	> EAPI
+	set +f
+	set                     >  environment
+	export | sed 's:^declare -rx:declare -x:' >> environment
+	bzip2 -f9 environment
+
+	cp "${EBUILD}" "${PF}.ebuild"
+	if hasq nostrip ${FEATURES} ${RESTRICT} || hasq strip ${RESTRICT}
+	then
+		touch DEBUGBUILD
+	fi
+
+	[ "$(type -t post_src_compile)" == "function" ] && qa_call post_src_compile
+
+	trap SIGINT SIGQUIT
+}
+
+dyn_test() {
+	[ "${EBUILD_FORCE_TEST}" == "1" ] && rm -f "${PORTAGE_BUILDDIR}/.tested"
+	[ "$(type -t pre_src_test)" == "function" ] && qa_call pre_src_test
+	if [ "${PORTAGE_BUILDDIR}/.tested" -nt "${WORKDIR}" ]; then
+		vecho ">>> It appears that ${PN} has already been tested; skipping."
+		[ "$(type -t post_src_test)" == "function" ] && qa_call post_src_test
+		return
+	fi
+	trap "abort_test" SIGINT SIGQUIT
+	if [ -d "${S}" ]; then
+		cd "${S}"
+	fi
+	if ! hasq test $FEATURES && [ "${EBUILD_FORCE_TEST}" != "1" ]; then
+		vecho ">>> Test phase [not enabled]: ${CATEGORY}/${PF}"
+	elif ! hasq test ${USE} && [ "${EBUILD_FORCE_TEST}" != "1" ]; then
+		ewarn "Skipping make test/check since USE=test is masked."
+		vecho ">>> Test phase [explicitly disabled]: ${CATEGORY}/${PF}"
+	elif hasq test $RESTRICT; then
+		ewarn "Skipping make test/check due to ebuild restriction."
+		vecho ">>> Test phase [explicitly disabled]: ${CATEGORY}/${PF}"
+	else
+		addpredict /
+		qa_call src_test
+		SANDBOX_PREDICT="${SANDBOX_PREDICT%:/}"
+	fi
+
+	cd "${PORTAGE_BUILDDIR}"
+	touch .tested || die "Failed to 'touch .tested' in ${PORTAGE_BUILDDIR}"
+	[ "$(type -t post_src_test)" == "function" ] && qa_call post_src_test
+	trap SIGINT SIGQUIT
+}
+
+dyn_install() {
+	[ -z "$PORTAGE_BUILDDIR" ] && die "${FUNCNAME}: PORTAGE_BUILDDIR is unset"
+	if hasq noauto $FEATURES ; then
+		rm -f "${PORTAGE_BUILDDIR}/.installed"
+	elif [[ ${PORTAGE_BUILDDIR}/.installed -nt ${WORKDIR} ]] ; then
+		vecho ">>> It appears that '${PF}' is already installed; skipping."
+		vecho ">>> Remove '${PORTAGE_BUILDDIR}/.installed' to force install."
+		return 0
+	fi
+	trap "abort_install" SIGINT SIGQUIT
+	[ "$(type -t pre_src_install)" == "function" ] && qa_call pre_src_install
+	rm -rf "${PORTAGE_BUILDDIR}/image"
+	mkdir "${PORTAGE_BUILDDIR}/image"
+	if [ -d "${S}" ]; then
+		cd "${S}"
+	fi
+	vecho
+	vecho ">>> Install ${PF} into ${D} category ${CATEGORY}"
+	#our custom version of libtool uses $S and $D to fix
+	#invalid paths in .la files
+	export S D
+	#some packages uses an alternative to $S to build in, cause
+	#our libtool to create problematic .la files
+	export PWORKDIR="$WORKDIR"
+	qa_call src_install
+	touch "${PORTAGE_BUILDDIR}/.installed"
+	vecho ">>> Completed installing ${PF} into ${D}"
+	vecho
+	cd ${PORTAGE_BUILDDIR}
+	[ "$(type -t post_src_install)" == "function" ] && qa_call post_src_install
+	trap SIGINT SIGQUIT
+}
+
+dyn_preinst() {
+	if [ -z "$IMAGE" ]; then
+		eerror "${FUNCNAME}: IMAGE is unset"
+		return 1
+	fi
+
+	[ "$(type -t pre_pkg_preinst)" == "function" ] && qa_call pre_pkg_preinst
+
+	declare -r D=${IMAGE}
+	pkg_preinst
+
+	[ "$(type -t post_pkg_preinst)" == "function" ] && qa_call post_pkg_preinst
+}
+
+dyn_help() {
+	echo
+	echo "Portage"
+	echo "Copyright 1999-2006 Gentoo Foundation"
+	echo
+	echo "How to use the ebuild command:"
+	echo
+	echo "The first argument to ebuild should be an existing .ebuild file."
+	echo
+	echo "One or more of the following options can then be specified.  If more"
+	echo "than one option is specified, each will be executed in order."
+	echo
+	echo "  help        : show this help screen"
+	echo "  setup       : execute package specific setup actions"
+	echo "  fetch       : download source archive(s) and patches"
+	echo "  digest      : create a digest and a manifest file for the package"
+	echo "  manifest    : create a manifest file for the package"
+	echo "  unpack      : unpack/patch sources (auto-fetch if needed)"
+	echo "  compile     : compile sources (auto-fetch/unpack if needed)"
+	echo "  test        : test package (auto-fetch/unpack/compile if needed)"
+	echo "  preinst     : execute pre-install instructions"
+	echo "  postinst    : execute post-install instructions"
+	echo "  install     : install the package to the temporary install directory"
+	echo "  qmerge      : merge image into live filesystem, recording files in db"
+	echo "  merge       : do fetch, unpack, compile, install and qmerge"
+	echo "  prerm       : execute pre-removal instructions"
+	echo "  postrm      : execute post-removal instructions"
+	echo "  unmerge     : remove package from live filesystem"
+	echo "  config      : execute package specific configuration actions"
+	echo "  package     : create a tarball package in ${PKGDIR}/All"
+	echo "  rpm         : build a RedHat RPM package"
+	echo "  clean       : clean up all source and temporary files"
+	echo
+	echo "The following settings will be used for the ebuild process:"
+	echo
+	echo "  package     : ${PF}"
+	echo "  slot        : ${SLOT}"
+	echo "  category    : ${CATEGORY}"
+	echo "  description : ${DESCRIPTION}"
+	echo "  system      : ${CHOST}"
+	echo "  c flags     : ${CFLAGS}"
+	echo "  c++ flags   : ${CXXFLAGS}"
+	echo "  make flags  : ${MAKEOPTS}"
+	echo -n "  build mode  : "
+	if hasq nostrip ${FEATURES} ${RESTRICT} || hasq strip ${RESTRICT} ;
+	then
+		echo "debug (large)"
+	else
+		echo "production (stripped)"
+	fi
+	echo "  merge to    : ${ROOT}"
+	echo
+	if [ -n "$USE" ]; then
+		echo "Additionally, support for the following optional features will be enabled:"
+		echo
+		echo "  ${USE}"
+	fi
+	echo
+}
+
+# debug-print() gets called from many places with verbose status information useful
+# for tracking down problems. The output is in $T/eclass-debug.log.
+# You can set ECLASS_DEBUG_OUTPUT to redirect the output somewhere else as well.
+# The special "on" setting echoes the information, mixing it with the rest of the
+# emerge output.
+# You can override the setting by exporting a new one from the console, or you can
+# set a new default in make.*. Here the default is "" or unset.
+
+# in the future might use e* from /etc/init.d/functions.sh if i feel like it
+debug-print() {
+	# if $T isn't defined, we're in dep calculation mode and
+	# shouldn't do anything
+	[ ! -d "$T" ] && return 0
+
+	while [ "$1" ]; do
+
+		# extra user-configurable targets
+		if [ "$ECLASS_DEBUG_OUTPUT" == "on" ]; then
+			echo "debug: $1"
+		elif [ -n "$ECLASS_DEBUG_OUTPUT" ]; then
+			echo "debug: $1" >> $ECLASS_DEBUG_OUTPUT
+		fi
+
+		# default target
+		echo "$1" >> "${T}/eclass-debug.log"
+		# let the portage user own/write to this file
+		chmod g+w "${T}/eclass-debug.log" &>/dev/null
+
+		shift
+	done
+}
+
+# The following 2 functions are debug-print() wrappers
+
+debug-print-function() {
+	str="$1: entering function"
+	shift
+	debug-print "$str, parameters: $*"
+}
+
+debug-print-section() {
+	debug-print "now in section $*"
+}
+
+# Sources all eclasses in parameters
+declare -ix ECLASS_DEPTH=0
+inherit() {
+	ECLASS_DEPTH=$(($ECLASS_DEPTH + 1))
+	if [[ ${ECLASS_DEPTH} > 1 ]]; then
+		debug-print "*** Multiple Inheritence (Level: ${ECLASS_DEPTH})"
+	fi
+
+	local location
+	local olocation
+	local PECLASS
+
+	local B_IUSE
+	local B_DEPEND
+	local B_RDEPEND
+	local B_PDEPEND
+	while [ "$1" ]; do
+		location="${ECLASSDIR}/${1}.eclass"
+		olocation=""
+
+		# PECLASS is used to restore the ECLASS var after recursion.
+		PECLASS="$ECLASS"
+		export ECLASS="$1"
+
+		if [ "${EBUILD_PHASE}" != "depend" ] && \
+			[[ ${EBUILD_PHASE} != *rm ]]; then
+			# This is disabled in the *rm phases because they frequently give
+			# false alarms due to INHERITED in /var/db/pkg being outdated
+			# in comparison the the eclasses from the portage tree.
+			if ! hasq $ECLASS $INHERITED; then
+				eqawarn "QA Notice: ECLASS '$ECLASS' inherited illegally in $CATEGORY/$PF"
+			fi
+		fi
+
+		# any future resolution code goes here
+		if [ -n "$PORTDIR_OVERLAY" ]; then
+			local overlay
+			for overlay in ${PORTDIR_OVERLAY}; do
+				olocation="${overlay}/eclass/${1}.eclass"
+				if [ -e "$olocation" ]; then
+					location="${olocation}"
+					debug-print "  eclass exists: ${location}"
+				fi
+			done
+		fi
+		debug-print "inherit: $1 -> $location"
+		[ ! -e "$location" ] && die "${1}.eclass could not be found by inherit()"
+
+		if [ "${location}" == "${olocation}" ] && \
+			! hasq "${location}" ${EBUILD_OVERLAY_ECLASSES} ; then
+				EBUILD_OVERLAY_ECLASSES="${EBUILD_OVERLAY_ECLASSES} ${location}"
+		fi
+
+		#We need to back up the value of DEPEND and RDEPEND to B_DEPEND and B_RDEPEND
+		#(if set).. and then restore them after the inherit call.
+
+		#turn off glob expansion
+		set -f
+
+		# Retain the old data and restore it later.
+		unset B_IUSE B_DEPEND B_RDEPEND B_PDEPEND
+		[ "${IUSE-unset}"    != "unset" ] && B_IUSE="${IUSE}"
+		[ "${DEPEND-unset}"  != "unset" ] && B_DEPEND="${DEPEND}"
+		[ "${RDEPEND-unset}" != "unset" ] && B_RDEPEND="${RDEPEND}"
+		[ "${PDEPEND-unset}" != "unset" ] && B_PDEPEND="${PDEPEND}"
+		unset IUSE DEPEND RDEPEND PDEPEND
+		#turn on glob expansion
+		set +f
+
+		qa_source "$location" || die "died sourcing $location in inherit()"
+		
+		#turn off glob expansion
+		set -f
+
+		# If each var has a value, append it to the global variable E_* to
+		# be applied after everything is finished. New incremental behavior.
+		[ "${IUSE-unset}"    != "unset" ] && export E_IUSE="${E_IUSE} ${IUSE}"
+		[ "${DEPEND-unset}"  != "unset" ] && export E_DEPEND="${E_DEPEND} ${DEPEND}"
+		[ "${RDEPEND-unset}" != "unset" ] && export E_RDEPEND="${E_RDEPEND} ${RDEPEND}"
+		[ "${PDEPEND-unset}" != "unset" ] && export E_PDEPEND="${E_PDEPEND} ${PDEPEND}"
+
+		[ "${B_IUSE-unset}"    != "unset" ] && IUSE="${B_IUSE}"
+		[ "${B_IUSE-unset}"    != "unset" ] || unset IUSE
+
+		[ "${B_DEPEND-unset}"  != "unset" ] && DEPEND="${B_DEPEND}"
+		[ "${B_DEPEND-unset}"  != "unset" ] || unset DEPEND
+
+		[ "${B_RDEPEND-unset}" != "unset" ] && RDEPEND="${B_RDEPEND}"
+		[ "${B_RDEPEND-unset}" != "unset" ] || unset RDEPEND
+
+		[ "${B_PDEPEND-unset}" != "unset" ] && PDEPEND="${B_PDEPEND}"
+		[ "${B_PDEPEND-unset}" != "unset" ] || unset PDEPEND
+
+		#turn on glob expansion
+		set +f
+
+		hasq $1 $INHERITED || export INHERITED="$INHERITED $1"
+
+		export ECLASS="$PECLASS"
+
+		shift
+	done
+	((--ECLASS_DEPTH)) # Returns 1 when ECLASS_DEPTH reaches 0.
+	return 0
+}
+
+# Exports stub functions that call the eclass's functions, thereby making them default.
+# For example, if ECLASS="base" and you call "EXPORT_FUNCTIONS src_unpack", the following
+# code will be eval'd:
+# src_unpack() { base_src_unpack; }
+EXPORT_FUNCTIONS() {
+	if [ -z "$ECLASS" ]; then
+		echo "EXPORT_FUNCTIONS without a defined ECLASS" >&2
+		exit 1
+	fi
+	while [ "$1" ]; do
+		debug-print "EXPORT_FUNCTIONS: ${1} -> ${ECLASS}_${1}"
+		eval "$1() { ${ECLASS}_$1 "\$@" ; }" > /dev/null
+		shift
+	done
+}
+
+# adds all parameters to E_DEPEND and E_RDEPEND, which get added to DEPEND
+# and RDEPEND after the ebuild has been processed. This is important to
+# allow users to use DEPEND="foo" without frying dependencies added by an
+# earlier inherit. It also allows RDEPEND to work properly, since a lot
+# of ebuilds assume that an unset RDEPEND gets its value from DEPEND.
+# Without eclasses, this is true. But with them, the eclass may set
+# RDEPEND itself (or at least used to) which would prevent RDEPEND from
+# getting its value from DEPEND. This is a side-effect that made eclasses
+# have unreliable dependencies.
+
+newdepend() {
+	debug-print-function newdepend $*
+	debug-print "newdepend: E_DEPEND=$E_DEPEND E_RDEPEND=$E_RDEPEND"
+
+	while [ -n "$1" ]; do
+		case $1 in
+		"/autotools")
+			do_newdepend DEPEND sys-devel/autoconf sys-devel/automake sys-devel/make
+			;;
+		"/c")
+			do_newdepend DEPEND sys-devel/gcc virtual/libc
+			do_newdepend RDEPEND virtual/libc
+			;;
+		*)
+			do_newdepend DEPEND $1
+			;;
+		esac
+		shift
+	done
+}
+
+newrdepend() {
+	debug-print-function newrdepend $*
+	do_newdepend RDEPEND $1
+}
+
+newpdepend() {
+	debug-print-function newpdepend $*
+	do_newdepend PDEPEND $1
+}
+
+do_newdepend() {
+	# This function does a generic change determining whether we're in an
+	# eclass or not. If we are, we change the E_* variables for deps.
+	debug-print-function do_newdepend $*
+	[ -z "$1" ] && die "do_newdepend without arguments"
+
+	# Grab what we're affecting... Figure out if we're affecting eclasses.
+	[[ ${ECLASS_DEPTH} > 0 ]] && TARGET="E_$1"
+	[[ ${ECLASS_DEPTH} > 0 ]] || TARGET="$1"
+	shift # $1 was a variable name.
+
+	while [ -n "$1" ]; do
+		# This bit of evil takes TARGET and uses it to evaluate down to a
+		# variable. This is a sneaky way to make this infinately expandable.
+		# The normal translation of this would look something like this:
+		# E_DEPEND="${E_DEPEND} $1"  ::::::  Cool, huh? :)
+		eval export ${TARGET}=\"\${${TARGET}} \$1\"
+		shift
+	done
+}
+
+# this is a function for removing any directory matching a passed in pattern from
+# PATH
+remove_path_entry() {
+	save_IFS
+	IFS=":"
+	stripped_path="${PATH}"
+	while [ -n "$1" ]; do
+		cur_path=""
+		for p in ${stripped_path}; do
+			if [ "${p/${1}}" == "${p}" ]; then
+				cur_path="${cur_path}:${p}"
+			fi
+		done
+		stripped_path="${cur_path#:*}"
+		shift
+	done
+	restore_IFS
+	PATH="${stripped_path}"
+}
+
+# === === === === === === === === === === === === === === === === === ===
+# === === === === === functions end, main part begins === === === === ===
+# === === === === === functions end, main part begins === === === === ===
+# === === === === === functions end, main part begins === === === === ===
+# === === === === === === === === === === === === === === === === === ===
+
+if [[ ${EBUILD_SH_ARGS} != "depend" ]] && [[ ${EBUILD_SH_ARGS}  != "clean" ]] && [[ ${EBUILD_SH_ARGS} != "setup" ]]; then
+	cd ${PORTAGE_TMPDIR} &> /dev/null
+	cd ${BUILD_PREFIX} &> /dev/null
+
+	if [ "$(id -nu)" == "portage" ] ; then
+		export USER=portage
+	fi
+
+	if hasq distcc ${FEATURES} ; then
+		if [ -d /usr/lib/distcc/bin ]; then
+			#We can enable distributed compile support
+			if [ -z "${PATH/*distcc*/}" ]; then
+				# Remove the other reference.
+				remove_path_entry "distcc"
+			fi
+			export PATH="/usr/lib/distcc/bin:${PATH}"
+			[ ! -z "${DISTCC_LOG}" ] && addwrite "$(dirname ${DISTCC_LOG})"
+		elif which distcc &>/dev/null; then
+			if ! hasq distcc $CC; then
+				export CC="distcc $CC"
+			fi
+			if ! hasq distcc $CXX; then
+				export CXX="distcc $CXX"
+			fi
+		fi
+	fi
+
+	if hasq ccache ${FEATURES} ; then
+		#We can enable compiler cache support
+		if [ -z "${PATH/*ccache*/}" ]; then
+			# Remove the other reference.
+			remove_path_entry "ccache"
+		fi
+
+		if [ -d /usr/lib/ccache/bin ]; then
+			export PATH="/usr/lib/ccache/bin:${PATH}"
+		elif [ -d /usr/bin/ccache ]; then
+			export PATH="/usr/bin/ccache:${PATH}"
+		fi
+
+		[ -z "${CCACHE_DIR}" ] && export CCACHE_DIR="/var/tmp/ccache"
+
+		addread "${CCACHE_DIR}"
+		addwrite "${CCACHE_DIR}"
+
+		[ -n "${CCACHE_SIZE}" ] && ccache -M ${CCACHE_SIZE} &> /dev/null
+	else
+		# Force configure scripts that automatically detect ccache to respect
+		# FEATURES="-ccache"
+		export CCACHE_DISABLE=1
+	fi
+
+	# XXX: Load up the helper functions.
+#	for X in /usr/lib/portage/bin/functions/*.sh; do
+#		source ${X} || die "Failed to source ${X}"
+#	done
+
+else
+
+killparent() {
+	trap INT
+	kill ${PORTAGE_MASTER_PID}
+}
+trap "killparent" INT
+
+fi # "$*"!="depend" && "$*"!="clean" && "$*" != "setup"
+
+export SANDBOX_ON="1"
+export S=${WORKDIR}/${P}
+
+unset E_IUSE E_DEPEND E_RDEPEND E_PDEPEND
+
+for x in T P PN PV PVR PR CATEGORY A EBUILD EMERGE_FROM O PPID FILESDIR PORTAGE_TMPDIR; do
+	[[ ${!x-UNSET_VAR} != UNSET_VAR ]] && declare -r ${x}
+done
+# Need to be able to change D in dyn_preinst due to the IMAGE stuff
+[[ ${EBUILD_SH_ARGS} != "preinst" ]] && declare -r D
+unset x
+
+# Turn of extended glob matching so that g++ doesn't get incorrectly matched.
+shopt -u extglob
+
+QA_INTERCEPTORS="javac java-config python python-config perl grep egrep fgrep sed gcc g++ cc bash awk nawk gawk pkg-config"
+# level the QA interceptors if we're in depend
+if hasq "depend" "${EBUILD_SH_ARGS}"; then
+	for BIN in ${QA_INTERCEPTORS}; do
+		BIN_PATH=$(type -Pf ${BIN})
+		if [ "$?" != "0" ]; then
+			BODY="echo \"*** missing command: ${BIN}\" >&2; return 127"
+		else
+			BODY="${BIN_PATH} \"\$@\"; return \$?"
+		fi
+		FUNC_SRC="${BIN}() {
+		if [ \$ECLASS_DEPTH -gt 0 ]; then
+			eqawarn \"QA Notice: '${BIN}' called in global scope: eclass \${ECLASS}\"
+		else
+			eqawarn \"QA Notice: '${BIN}' called in global scope: \${CATEGORY}/\${PF}\"
+		fi
+		${BODY}
+		}";
+		eval "$FUNC_SRC" || echo "error creating QA interceptor ${BIN}" >&2
+	done
+	unset BIN_PATH BIN BODY FUNC_SRC
+fi
+
+# reset the EBUILD_DEATH_HOOKS so they don't multiple due to stable's re-sourcing of env.
+# this can be left out of ebd variants, since they're unaffected.
+unset EBUILD_DEATH_HOOKS
+
+# *DEPEND and IUSE will be set during the sourcing of the ebuild.  In order to
+# ensure correct interaction between ebuilds and eclasses, they need to be
+# unset before this process of interaction begins.
+unset DEPEND RDEPEND PDEPEND IUSE
+
+source ${EBUILD} || die "error sourcing ebuild"
+if ! hasq depend $EBUILD_PHASE; then
+	RESTRICT="${PORTAGE_RESTRICT}"
+	unset PORTAGE_RESTRICT
+fi
+
+# Expand KEYWORDS
+# We need to turn off pathname expansion for -* in KEYWORDS and
+# we need to escape ~ to avoid tilde expansion
+set -f
+KEYWORDS=$(eval echo ${KEYWORDS//~/\\~})
+set +f
+
+if hasq nostrip ${FEATURES} ${RESTRICT} || hasq strip ${RESTRICT}
+then
+	export DEBUGBUILD=1
+fi
+
+#a reasonable default for $S
+if [ "$S" = "" ]; then
+	export S=${WORKDIR}/${P}
+fi
+
+#wipe the interceptors.  we don't want saved.
+if hasq "depend" "${EBUILD_SH_ARGS}"; then
+	unset -f $QA_INTERCEPTORS
+	unset QA_INTERCEPTORS
+fi
+
+#some users have $TMP/$TMPDIR to a custom dir in their home ...
+#this will cause sandbox errors with some ./configure
+#scripts, so set it to $T.
+export TMP="${T}"
+export TMPDIR="${T}"
+
+# Note: this next line is not the same as export RDEPEND=${RDEPEND:-${DEPEND}}
+# That will test for unset *or* NULL ("").  We want just to set for unset...
+
+#turn off glob expansion from here on in to prevent *'s and ? in the DEPEND
+#syntax from getting expanded :)
+#check eclass rdepends also.
+set -f
+if [ "${RDEPEND-unset}" == "unset" ] ; then
+	export RDEPEND=${DEPEND}
+	debug-print "RDEPEND: not set... Setting to: ${DEPEND}"
+fi
+
+#add in dependency info from eclasses
+IUSE="$IUSE $E_IUSE"
+DEPEND="$DEPEND $E_DEPEND"
+RDEPEND="$RDEPEND $E_RDEPEND"
+PDEPEND="$PDEPEND $E_PDEPEND"
+
+unset E_IUSE E_DEPEND E_RDEPEND E_PDEPEND
+
+if [ "${EBUILD_PHASE}" != "depend" ]; then
+	# Make IUSE defaults backward compatible with all the old shell code.
+	iuse_temp=""
+	for x in ${IUSE} ; do
+		if [[ ${x} == +* ]]; then
+			iuse_temp="${iuse_temp} ${x:1}"
+		else
+			iuse_temp="${iuse_temp} ${x}"
+		fi
+	done
+	export IUSE=${iuse_temp}
+	unset iuse_temp
+	# Lock the dbkey variables after the global phase
+	declare -r DEPEND RDEPEND SLOT SRC_URI RESTRICT HOMEPAGE LICENSE DESCRIPTION
+	declare -r KEYWORDS INHERITED IUSE PDEPEND PROVIDE
+fi
+
+set +f
+
+for myarg in ${EBUILD_SH_ARGS} ; do
+	case $myarg in
+	nofetch)
+		qa_call pkg_nofetch
+		exit 1
+		;;
+	prerm|postrm|postinst|config)
+		export SANDBOX_ON="0"
+		if [ "$PORTAGE_DEBUG" != "1" ]; then
+			[ "$(type -t pre_pkg_${myarg})" == "function" ] && qa_call pre_pkg_${myarg}
+			qa_call pkg_${myarg}
+			[ "$(type -t post_pkg_${myarg})" == "function" ] && qa_call post_pkg_${myarg}
+			#Allow non-zero return codes since they can be caused by &&
+		else
+			set -x
+			[ "$(type -t pre_pkg_${myarg})" == "function" ] && qa_call pre_pkg_${myarg}
+			qa_call pkg_${myarg}
+			[ "$(type -t post_pkg_${myarg})" == "function" ] && qa_call post_pkg_${myarg}
+			#Allow non-zero return codes since they can be caused by &&
+			set +x
+		fi
+		;;
+	unpack|compile|test|clean|install)
+		if [ "${SANDBOX_DISABLED="0"}" == "0" ]; then
+			export SANDBOX_ON="1"
+		else
+			export SANDBOX_ON="0"
+		fi
+		if [ "$PORTAGE_DEBUG" != "1" ]; then
+			dyn_${myarg}
+			#Allow non-zero return codes since they can be caused by &&
+		else
+			set -x
+			dyn_${myarg}
+			#Allow non-zero return codes since they can be caused by &&
+			set +x
+		fi
+		export SANDBOX_ON="0"
+		;;
+	help|setup|preinst)
+		#pkg_setup needs to be out of the sandbox for tmp file creation;
+		#for example, awking and piping a file in /tmp requires a temp file to be created
+		#in /etc.  If pkg_setup is in the sandbox, both our lilo and apache ebuilds break.
+		export SANDBOX_ON="0"
+		if [ "$PORTAGE_DEBUG" != "1" ]; then
+			dyn_${myarg}
+		else
+			set -x
+			dyn_${myarg}
+			set +x
+		fi
+		;;
+	depend)
+		export SANDBOX_ON="0"
+		set -f
+
+		if [ -n "${dbkey}" ] ; then
+			if [ ! -d "${dbkey%/*}" ]; then
+				install -d -g ${PORTAGE_GID} -m2775 "${dbkey%/*}"
+			fi
+			# Make it group writable. 666&~002==664
+			umask 002
+		fi
+
+		auxdbkeys="DEPEND RDEPEND SLOT SRC_URI RESTRICT HOMEPAGE LICENSE
+			DESCRIPTION KEYWORDS INHERITED IUSE CDEPEND PDEPEND PROVIDE EAPI
+			UNUSED_01 UNUSED_02 UNUSED_03 UNUSED_04 UNUSED_05 UNUSED_06
+			UNUSED_07"
+
+		#the extra $(echo) commands remove newlines
+		unset CDEPEND
+		[ -n "${EAPI}" ] || EAPI=0
+		if [ -n "${dbkey}" ] ; then
+			> "${dbkey}"
+			for f in ${auxdbkeys} ; do
+				echo $(echo ${!f}) >> "${dbkey}" || exit $?
+			done
+		else
+			for f in ${auxdbkeys} ; do
+				echo $(echo ${!f}) 1>&9 || exit $?
+			done
+			9>&-
+		fi
+		set +f
+		#make sure it is writable by our group:
+		exit 0
+		;;
+	*)
+		export SANDBOX_ON="1"
+		echo "Please specify a valid command."
+		echo
+		dyn_help
+		exit 1
+		;;
+	esac
+
+	#if [ $? -ne 0 ]; then
+	#	exit 1
+	#fi
+done
+
+# Save the env only for relevant phases.
+if [ -n "${myarg}" ] && \
+	[ "${myarg}" != "clean" ] && \
+	[ "${myarg}" != "help" ] ; then
+	# Do not save myarg in the env, or else the above [ -n "$myarg" ] test will
+	# give a false positive when ebuild.sh is sourced.
+	unset myarg
+	# Save current environment and touch a success file. (echo for success)
+	umask 002
+	set | egrep -v "^SANDBOX_" > "${T}/environment" 2>/dev/null
+	export | egrep -v "^declare -x SANDBOX_" | \
+		sed 's:^declare -rx:declare -x:' >> "${T}/environment" 2>/dev/null
+	chown portage:portage "${T}/environment" &>/dev/null
+	chmod g+w "${T}/environment" &>/dev/null
+fi
+
+# Do not exit when ebuild.sh is sourced by other scripts.
+true
Index: /vendor/portage/current/bin/ecompress
===================================================================
--- /vendor/portage/current/bin/ecompress	(revision 3419)
+++ /vendor/portage/current/bin/ecompress	(revision 3419)
@@ -0,0 +1,52 @@
+#!/bin/bash
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: prepman 5507 2007-01-10 04:22:27Z zmedico $
+
+source "${PORTAGE_BIN_PATH:-/usr/lib/portage/bin}"/isolated-functions.sh
+
+if [[ -z $1 ]] ; then
+	vecho "${0##*/}: at least one argument needed" 1>&2
+	exit 1
+fi
+
+# setup compression stuff
+PORTAGE_COMPRESS=${PORTAGE_COMPRESS-bzip2}
+[[ -z ${PORTAGE_COMPRESS} ]] && exit 0
+
+if [[ ${PORTAGE_COMPRESS_FLAGS+set} != "set" ]] ; then
+	case ${PORTAGE_COMPRESS} in
+		bzip2|gzip)  PORTAGE_COMPRESS_FLAGS="-9";;
+	esac
+fi
+
+case $1 in
+	--suffix)
+		set -e
+		tmpdir="${T}"/.ecompress$$.${RANDOM}
+		mkdir "${tmpdir}"
+		cd "${tmpdir}"
+		# we have to fill the file enough so that there is something
+		# to compress as some programs will refuse to do compression
+		# if it cannot actually compress the file
+		echo {0..1000} > compressme
+		${PORTAGE_COMPRESS} ${PORTAGE_COMPRESS_FLAGS} compressme > /dev/null
+		suffix=$(ls compressme*)
+		suffix=${suffix#compressme}
+		cd /
+		rm -rf "${tmpdir}"
+		echo "${suffix}"
+		;;
+	--bin)
+		echo "${PORTAGE_COMPRESS} ${PORTAGE_COMPRESS_FLAGS}"
+		;;
+	*)
+		# If a compressed version of the file already exists, simply
+		# delete it so that the compressor doesn't whine (bzip2 will
+		# complain and skip, gzip will prompt for input)
+		suffix=$(ecompress --suffix)
+		[[ -n ${suffix} ]] && rm -f "${@/%/${suffix}}"
+		# Finally, let's actually do some real work
+		exec "${PORTAGE_COMPRESS}" ${PORTAGE_COMPRESS_FLAGS} "$@"
+		;;
+esac
Index: /vendor/portage/current/bin/ecompressdir
===================================================================
--- /vendor/portage/current/bin/ecompressdir	(revision 3419)
+++ /vendor/portage/current/bin/ecompressdir	(revision 3419)
@@ -0,0 +1,73 @@
+#!/bin/bash
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: prepalldocs 3483 2006-06-10 21:40:40Z genone $
+
+source "${PORTAGE_BIN_PATH:-/usr/lib/portage/bin}"/isolated-functions.sh
+
+if [[ -z $1 ]] ; then
+	vecho "${0##*/}: at least one argument needed" 1>&2
+	exit 1
+fi
+
+# figure out the new suffix
+suffix=$(ecompress --suffix)
+
+# funk_up_dir(action, suffix, binary)
+#	- action: compress or decompress
+#	- suffix: the compression suffix to work with
+#	- binary: the program to execute that'll compress/decompress
+# The directory we act on is implied in the ${dir} variable
+funk_up_dir() {
+	local act=$1 suffix=$2 binary=$3
+
+	local negate=""
+	[[ ${act} == "compress" ]] && negate="!"
+
+	# first we act on all the files
+	find "${dir}" -type f ${negate} -iname '*'${suffix} -print0 | ${XARGS} -0 ${binary}
+	((ret+=$?))
+
+	find "${dir}" -type l -print0 | \
+	while read -d $'\0' brokenlink ; do
+		[[ -e ${brokenlink} ]] && continue
+		olddest=$(readlink "${brokenlink}")
+		[[ ${act} == "compress" ]] \
+			&& newdest="${olddest}${suffix}" \
+			|| newdest="${olddest%${suffix}}"
+		rm -f "${brokenlink}"
+		[[ ${act} == "compress" ]] \
+			&& ln -snf "${newdest}" "${brokenlink}${suffix}" \
+			|| ln -snf "${newdest}" "${brokenlink%${suffix}}"
+		((ret+=$?))
+	done
+}
+
+ret=0
+
+for dir in "$@" ; do
+	dir="${D}${dir}"
+	if [[ ! -d ${dir} ]] ; then
+		vecho "${0##*/}: ${dir#${D}} does not exist!"
+		continue
+	fi
+	cd "${dir}"
+	actual_dir=${dir}
+	dir=. # use relative path to avoid 'Argument list too long' errors
+
+	# not uncommon for packages to compress doc files themselves
+	funk_up_dir "decompress" ".Z" "gunzip"
+	funk_up_dir "decompress" ".gz" "gunzip"
+	funk_up_dir "decompress" ".bz2" "bunzip2"
+
+	# forcibly break all hard links as some compressors whine about it
+	find "${dir}" -type f -links +1 -exec env file="{}" sh -c \
+		'cp -p "${file}" "${file}.ecompress.break" ; mv -f "${file}.ecompress.break" "${file}"' \;
+
+	# now lets do our work
+	[[ -z ${suffix} ]] && continue
+	vecho "${0##*/}: $(ecompress --bin) ${actual_dir#${D}}"
+	funk_up_dir "compress" "${suffix}" "ecompress"
+done
+
+exit ${ret}
Index: /vendor/portage/current/bin/emaint
===================================================================
--- /vendor/portage/current/bin/emaint	(revision 3419)
+++ /vendor/portage/current/bin/emaint	(revision 3419)
@@ -0,0 +1,196 @@
+#!/usr/bin/python -O
+
+import sys, os
+from optparse import OptionParser, OptionValueError
+if not hasattr(__builtins__, "set"):
+	from sets import Set as set
+import re
+try:
+	import portage
+except ImportError:
+	from os import path as osp
+	sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
+	import portage
+
+import portage_const, portage_exception
+class WorldHandler(object):
+
+	def name():
+		return "world"
+	name = staticmethod(name)
+
+	def __init__(self):
+		self.invalid = []
+		self.not_installed = []
+		self.invalid_category = []
+		self.okay = []
+		self.world_file = os.path.join("/", portage_const.WORLD_FILE)
+		self.found = os.access(self.world_file, os.R_OK)
+
+		categories = set(portage.settings.categories)
+		myroot = portage.settings["ROOT"]
+		vardb = portage.db[myroot]["vartree"].dbapi
+
+		for atom in open(self.world_file).read().split():
+			if not portage.isvalidatom(atom):
+				self.invalid.append(atom)
+				continue
+			okay = True
+			if not vardb.match(atom):
+				self.not_installed.append(atom)
+				okay = False
+			if portage.catsplit(atom)[0] not in categories:
+				self.invalid_category.append(atom)
+				okay = False
+			if okay:
+				self.okay.append(atom)
+
+	def check(self):
+		errors = []
+		if self.found:
+			errors += map(lambda x: "'%s' is not a valid atom" % x, self.invalid)
+			errors += map(lambda x: "'%s' is not installed" % x, self.not_installed)
+			errors += map(lambda x: "'%s' has a category that is not listed in /etc/portage/categories" % x, self.invalid_category)
+		else:
+			errors.append(self.world_file + " could not be opened for reading")
+		return errors
+
+	def fix(self):
+		errors = []
+		try:
+			portage.write_atomic(self.world_file, "\n".join(self.okay))
+		except portage_exception.PortageException:
+			errors.append(self.world_file + " could not be opened for writing")
+		return errors
+
+class VdbKeyHandler(object):
+	def name():
+		return "vdbkeys"
+	name = staticmethod(name)
+
+	def __init__(self):
+		self.list = portage.db["/"]["vartree"].dbapi.cpv_all()
+		self.missing = []
+		self.keys = ["HOMEPAGE", "SRC_URI", "KEYWORDS", "DESCRIPTION"]
+		
+		for p in self.list:
+			mydir = os.path.join(os.sep, portage.settings["ROOT"], portage_const.VDB_PATH, p)+os.sep
+			ismissing = True
+			for k in self.keys:
+				if os.path.exists(mydir+k):
+					ismissing = False
+					break
+			if ismissing:
+				self.missing.append(p)
+		
+	def check(self):
+		return ["%s has missing keys" % x for x in self.missing]
+	
+	def fix(self):
+	
+		errors = []
+	
+		for p in self.missing:
+			mydir = os.path.join(os.sep, portage.settings["ROOT"], portage_const.VDB_PATH, p)+os.sep
+			if not os.access(mydir+"environment.bz2", os.R_OK):
+				errors.append("Can't access %s" % (mydir+"environment.bz2"))
+			elif not os.access(mydir, os.W_OK):
+				errors.append("Can't create files in %s" % mydir)
+			else:
+				env = os.popen("bzip2 -dcq "+mydir+"environment.bz2", "r")
+				envlines = env.read().split("\n")
+				env.close()
+				for k in self.keys:
+					s = [l for l in envlines if l.startswith(k+"=")]
+					if len(s) > 1:
+						errors.append("multiple matches for %s found in %senvironment.bz2" % (k, mydir))
+					elif len(s) == 0:
+						s = ""
+					else:
+						s = s[0].split("=",1)[1]
+						s = s.lstrip("$").strip("\'\"")
+						s = re.sub("(\\\\[nrt])+", " ", s)
+						s = " ".join(s.split()).strip()
+						if s != "":
+							try:
+								keyfile = open(mydir+os.sep+k, "w")
+								keyfile.write(s+"\n")
+								keyfile.close()
+							except (IOError, OSError), e:
+								errors.append("Could not write %s, reason was: %s" % (mydir+k, e))
+		
+		return errors
+
+def emaint_main(myargv):
+
+	# TODO: Create a system that allows external modules to be added without
+	#       the need for hard coding.
+	modules = {"world" : WorldHandler}
+
+	module_names = modules.keys()
+	module_names.sort()
+	module_names.insert(0, "all")
+
+	def exclusive(option, *args, **kw):
+		var = kw.get("var", None)
+		if var is None:
+			raise ValueError("var not specified to exclusive()")
+		if getattr(parser, var, ""):
+			raise OptionValueError("%s and %s are exclusive options" % (getattr(parser, var), option))
+		setattr(parser, var, str(option))
+
+
+	usage = "usage: emaint [options] " + " | ".join(module_names)
+
+	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."
+
+
+	parser = OptionParser(usage=usage)
+	parser.add_option("-c", "--check", help="check for problems",
+		action="callback", callback=exclusive, callback_kwargs={"var":"action"})
+	parser.add_option("-f", "--fix", help="attempt to fix problems",
+		action="callback", callback=exclusive, callback_kwargs={"var":"action"})
+	parser.action = None
+
+
+	(options, args) = parser.parse_args(args=myargv)
+	if len(args) != 1:
+		parser.error("Incorrect number of arguments")
+	if args[0] not in module_names:
+		parser.error("%s target is not a known target" % args[0])
+
+	if parser.action:
+		action = parser.action
+	else:
+		print "Defaulting to --check"
+		action = "-c/--check"
+
+	if args[0] == "all":
+		tasks = modules.values()
+	else:
+		tasks = [modules[args[0]]]
+
+
+	if action == "-c/--check":
+		status = "Checking %s for problems"
+		func = "check"
+	else:
+		status = "Attempting to fix %s"
+		func = "fix"
+
+
+	for task in tasks:
+		print status % task.name()
+		inst = task()
+		result = getattr(inst, func)()
+		if result:
+			print
+			print "\n".join(result)
+			print "\n"
+
+	print "Finished"
+
+if __name__ == "__main__":
+	emaint_main(sys.argv[1:])
Index: /vendor/portage/current/bin/emake
===================================================================
--- /vendor/portage/current/bin/emake	(revision 3419)
+++ /vendor/portage/current/bin/emake	(revision 3419)
@@ -0,0 +1,14 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: emake 3483 2006-06-10 21:40:40Z genone $
+#
+# emake: Supplies some default parameters to GNU make. At the moment the
+#        only parameter supplied is -jN, where N is a number of
+#        parallel processes that should be ideal for the running host
+#        (e.g. on a single-CPU machine, N=2).  The MAKEOPTS variable
+#        is set in /etc/make.globals.  We don't source
+#        /etc/make.globals here because emake is only called from an
+#        ebuild.
+
+exec ${MAKE:-make} ${MAKEOPTS} ${EXTRA_EMAKE} "$@"
Index: /vendor/portage/current/bin/emerge
===================================================================
--- /vendor/portage/current/bin/emerge	(revision 3419)
+++ /vendor/portage/current/bin/emerge	(revision 3419)
@@ -0,0 +1,5531 @@
+#!/usr/bin/python -O
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: emerge 5629 2007-01-13 08:54:35Z zmedico $
+
+import sys
+# This block ensures that ^C interrupts are handled quietly.
+try:
+	import signal
+
+	def exithandler(signum,frame):
+		signal.signal(signal.SIGINT, signal.SIG_IGN)
+		signal.signal(signal.SIGTERM, signal.SIG_IGN)
+		sys.exit(1)
+	
+	signal.signal(signal.SIGINT, exithandler)
+	signal.signal(signal.SIGTERM, exithandler)
+	signal.signal(signal.SIGPIPE, signal.SIG_DFL)
+
+except KeyboardInterrupt:
+	sys.exit(1)
+
+import os, stat
+
+os.environ["PORTAGE_LEGACY_GLOBALS"] = "false"
+try:
+	import portage
+except ImportError:
+	from os import path as osp
+	sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
+	import portage
+del os.environ["PORTAGE_LEGACY_GLOBALS"]
+from portage import digraph
+
+import emergehelp, xpak, commands, errno, re, socket, time, types
+import output
+from output import blue, bold, colorize, darkblue, darkgreen, darkred, green, \
+	havecolor, nc_len, nocolor, red, teal, turquoise, white, xtermTitle, \
+	xtermTitleReset, yellow
+from output import create_color_func
+good = create_color_func("GOOD")
+bad = create_color_func("BAD")
+
+import portage_dep
+portage_dep._dep_check_strict = True
+import portage_util
+import portage_locks
+import portage_exception
+from portage_data import secpass
+from portage_util import normalize_path as normpath
+
+if not hasattr(__builtins__, "set"):
+	from sets import Set as set
+from itertools import chain, izip
+from UserDict import DictMixin
+
+try:
+	import cPickle
+except ImportError:
+	import pickle as cPickle
+
+class stdout_spinner(object):
+	scroll_msgs = [
+		"Gentoo Rocks ("+os.uname()[0]+")",
+		"Thank you for using Gentoo. :)",
+		"Are you actually trying to read this?",
+		"How many times have you stared at this?",
+		"We are generating the cache right now",
+		"You are paying too much attention.",
+		"A theory is better than its explanation.",
+		"Phasers locked on target, Captain.",
+		"Thrashing is just virtual crashing.",
+		"To be is to program.",
+		"Real Users hate Real Programmers.",
+		"When all else fails, read the instructions.",
+		"Functionality breeds Contempt.",
+		"The future lies ahead.",
+		"3.1415926535897932384626433832795028841971694",
+		"Sometimes insanity is the only alternative.",
+		"Inaccuracy saves a world of explanation.",
+	]
+
+	twirl_sequence = "/-\\|/-\\|/-\\|/-\\|\\-/|\\-/|\\-/|\\-/|"
+
+	def __init__(self):
+		self.spinpos = 0
+		self.update = self.update_twirl
+		self.scroll_sequence = self.scroll_msgs[
+			int(time.time() * 100) % len(self.scroll_msgs)]
+
+	def update_basic(self):
+		self.spinpos = (self.spinpos + 1) % 500
+		if (self.spinpos % 100) == 0:
+			if self.spinpos == 0:
+				sys.stdout.write(". ")
+			else:
+				sys.stdout.write(".")
+		sys.stdout.flush()
+
+	def update_scroll(self):
+		if(self.spinpos >= len(self.scroll_sequence)):
+			sys.stdout.write(darkgreen(" \b\b\b" + self.scroll_sequence[
+				len(self.scroll_sequence) - 1 - (self.spinpos % len(self.scroll_sequence))]))
+		else:
+			sys.stdout.write(green("\b " + self.scroll_sequence[self.spinpos]))
+		sys.stdout.flush()
+		self.spinpos = (self.spinpos + 1) % (2 * len(self.scroll_sequence))
+
+	def update_twirl(self):
+		self.spinpos = (self.spinpos + 1) % len(self.twirl_sequence)
+		sys.stdout.write("\b\b " + self.twirl_sequence[self.spinpos])
+		sys.stdout.flush()
+
+	def update_quiet(self):
+		return
+
+def userquery(prompt, responses=None, colours=None):
+	"""Displays a prompt and a set of responses, then waits for a response
+	which is checked against the responses and the first to match is
+	returned.  An empty response will match the first value in responses.  The
+	input buffer is *not* cleared prior to the prompt!
+
+	prompt: a String.
+	responses: a List of Strings.
+	colours: a List of Functions taking and returning a String, used to
+	process the responses for display. Typically these will be functions
+	like red() but could be e.g. lambda x: "DisplayString".
+	If responses is omitted, defaults to ["Yes", "No"], [green, red].
+	If only colours is omitted, defaults to [bold, ...].
+
+	Returns a member of the List responses. (If called without optional
+	arguments, returns "Yes" or "No".)
+	KeyboardInterrupt is converted to SystemExit to avoid tracebacks being
+	printed."""
+	if responses is None:
+		responses, colours = ["Yes", "No"], [green, red]
+	elif colours is None:
+		colours=[bold]
+	colours=(colours*len(responses))[:len(responses)]
+	print bold(prompt),
+	try:
+		while True:
+			response=raw_input("["+"/".join([colours[i](responses[i]) for i in range(len(responses))])+"] ")
+			for key in responses:
+				# An empty response will match the first value in responses.
+				if response.upper()==key[:len(response)].upper():
+					return key
+			print "Sorry, response '%s' not understood." % response,
+	except (EOFError, KeyboardInterrupt):
+		print "Interrupted."
+		sys.exit(1)
+
+actions=[
+"clean", "config", "depclean",
+"info", "metadata",
+"prune", "regen",  "search",
+"sync",  "system", "unmerge",  "world",
+]
+options=[
+"--ask",          "--alphabetical",
+"--buildpkg",     "--buildpkgonly",
+"--changelog",    "--columns",
+"--debug",        "--deep",
+"--digest",
+"--emptytree",
+"--fetchonly",    "--fetch-all-uri",
+"--getbinpkg",    "--getbinpkgonly",
+"--help",         "--ignore-default-opts",
+"--noconfmem",
+"--newuse",       "--nocolor",
+"--nodeps",       "--noreplace",
+"--nospinner",    "--oneshot",
+"--onlydeps",     "--pretend",
+"--quiet",        "--resume",
+"--searchdesc",   "--selective",
+"--skipfirst",
+"--tree",
+"--update",       
+"--usepkg",       "--usepkgonly",
+"--verbose",      "--version"
+]
+
+shortmapping={
+"1":"--oneshot",
+"a":"--ask",
+"b":"--buildpkg",  "B":"--buildpkgonly",
+"c":"--clean",     "C":"--unmerge",
+"d":"--debug",     "D":"--deep",
+"e":"--emptytree",
+"f":"--fetchonly", "F":"--fetch-all-uri",
+"g":"--getbinpkg", "G":"--getbinpkgonly",
+"h":"--help",
+"k":"--usepkg",    "K":"--usepkgonly",
+"l":"--changelog",
+"n":"--noreplace", "N":"--newuse",
+"o":"--onlydeps",  "O":"--nodeps",
+"p":"--pretend",   "P":"--prune",
+"q":"--quiet",
+"s":"--search",    "S":"--searchdesc",
+'t':"--tree",
+"u":"--update",
+"v":"--verbose",   "V":"--version"
+}
+
+def emergelog(xterm_titles, mystr, short_msg=None):
+	if xterm_titles:
+		if short_msg:
+			xtermTitle(short_msg)
+		else:
+			xtermTitle(mystr)
+	try:
+		file_path = "/var/log/emerge.log"
+		mylogfile = open(file_path, "a")
+		portage_util.apply_secpass_permissions(file_path,
+			uid=portage.portage_uid, gid=portage.portage_gid,
+			mode=0660)
+		mylock = None
+		try:
+			mylock = portage_locks.lockfile(mylogfile)
+			# seek because we may have gotten held up by the lock.
+			# if so, we may not be positioned at the end of the file.
+			mylogfile.seek(0, 2)
+			mylogfile.write(str(time.time())[:10]+": "+mystr+"\n")
+			mylogfile.flush()
+		finally:
+			if mylock:
+				portage_locks.unlockfile(mylock)
+			mylogfile.close()
+	except (IOError,OSError,portage_exception.PortageException), e:
+		if secpass >= 1:
+			print >> sys.stderr, "emergelog():",e
+
+def countdown(secs=5, doing="Starting"):
+	if secs:
+		print ">>> Waiting",secs,"seconds before starting..."
+		print ">>> (Control-C to abort)...\n"+doing+" in: ",
+		ticks=range(secs)
+		ticks.reverse()
+		for sec in ticks:
+			sys.stdout.write(colorize("UNMERGE_WARN", str(sec+1)+" "))
+			sys.stdout.flush()
+			time.sleep(1)
+		print
+
+# formats a size given in bytes nicely
+def format_size(mysize):
+	if type(mysize) not in [types.IntType,types.LongType]:
+		return str(mysize)
+	if 0 != mysize % 1024:
+		# Always round up to the next kB so that it doesn't show 0 kB when
+		# some small file still needs to be fetched.
+		mysize += 1024 - mysize % 1024
+	mystr=str(mysize/1024)
+	mycount=len(mystr)
+	while (mycount > 3):
+		mycount-=3
+		mystr=mystr[:mycount]+","+mystr[mycount:]
+	return mystr+" kB"
+
+
+def getgccversion(chost):
+	"""
+	rtype: C{str}
+	return:  the current in-use gcc version
+	"""
+
+	gcc_ver_command = 'gcc -dumpversion'
+	gcc_ver_prefix = 'gcc-'
+
+	gcc_not_found_error = red(
+	"!!! No gcc found. You probably need to 'source /etc/profile'\n" +
+	"!!! to update the environment of this terminal and possibly\n" +
+	"!!! other terminals also.\n"
+	)
+
+	mystatus, myoutput = commands.getstatusoutput("eselect compiler show")
+	if mystatus == os.EX_OK and len(myoutput.split("/")) == 2:
+		part1, part2 = myoutput.split("/")
+		if part1.startswith(chost + "-"):
+			return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
+
+	mystatus, myoutput = commands.getstatusoutput("gcc-config -c")
+	if mystatus == os.EX_OK and myoutput.startswith(chost + "-"):
+		return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
+
+	mystatus, myoutput = commands.getstatusoutput(
+		chost + "-" + gcc_ver_command)
+	if mystatus == os.EX_OK:
+		return gcc_ver_prefix + myoutput
+
+	mystatus, myoutput = commands.getstatusoutput(gcc_ver_command)
+	if mystatus == os.EX_OK:
+		return gcc_ver_prefix + myoutput
+
+	portage.writemsg(gcc_not_found_error, noiselevel=-1)
+	return "[unavailable]"
+
+def getportageversion(portdir, target_root, profile, chost, vardb):
+	profilever = "unavailable"
+	if profile:
+		realpath = os.path.realpath(profile)
+		basepath   = os.path.realpath(os.path.join(portdir, "profiles"))
+		if realpath.startswith(basepath):
+			profilever = realpath[1 + len(basepath):]
+		else:
+			try:
+				profilever = "!" + os.readlink(profile)
+			except (OSError):
+				pass
+		del realpath, basepath
+
+	libcver=[]
+	libclist  = vardb.match("virtual/libc")
+	libclist += vardb.match("virtual/glibc")
+	libclist  = portage_util.unique_array(libclist)
+	for x in libclist:
+		xs=portage.catpkgsplit(x)
+		if libcver:
+			libcver+=","+"-".join(xs[1:])
+		else:
+			libcver="-".join(xs[1:])
+	if libcver==[]:
+		libcver="unavailable"
+
+	gccver = getgccversion(chost)
+	unameout=os.uname()[2]+" "+os.uname()[4]
+
+	return "Portage " + portage.VERSION +" ("+profilever+", "+gccver+", "+libcver+", "+unameout+")"
+
+def create_depgraph_params(myopts, myaction):
+	#configure emerge engine parameters
+	#
+	# self:      include _this_ package regardless of if it is merged.
+	# selective: exclude the package if it is merged
+	# recurse:   go into the dependencies
+	# deep:      go into the dependencies of already merged packages
+	# empty:     pretend nothing is merged
+	myparams = ["recurse"]
+	add=[]
+	sub=[]
+	if "--update" in myopts or \
+		"--newuse" in myopts or \
+		"--noreplace" in myopts or \
+		myaction in ("system", "world"):
+		add.extend(["selective"])
+	if "--emptytree" in myopts:
+		add.extend(["empty"])
+		sub.extend(["selective"])
+	if "--nodeps" in myopts:
+		sub.extend(["recurse"])
+	if "--deep" in myopts:
+		add.extend(["deep"])
+	for x in add:
+		if (x not in myparams) and (x not in sub):
+			myparams.append(x)
+	for x in sub:
+		if x in myparams:
+			myparams.remove(x)
+	return myparams
+
+# search functionality
+class search:
+
+	#
+	# class constants
+	#
+	VERSION_SHORT=1
+	VERSION_RELEASE=2
+
+	#
+	# public interface
+	#
+	def __init__(self, settings, portdb, vartree, spinner, searchdesc,
+		verbose):
+		"""Searches the available and installed packages for the supplied search key.
+		The list of available and installed packages is created at object instantiation.
+		This makes successive searches faster."""
+		self.settings = settings
+		self.portdb = portdb
+		self.vartree = vartree
+		self.spinner = spinner
+		self.verbose = verbose
+		self.searchdesc = searchdesc
+
+	def execute(self,searchkey):
+		"""Performs the search for the supplied search key"""
+		match_category = 0
+		self.searchkey=searchkey
+		self.packagematches = []
+		if self.searchdesc:
+			self.searchdesc=1
+			self.matches = {"pkg":[], "desc":[]}
+		else:
+			self.searchdesc=0
+			self.matches = {"pkg":[]}
+		print "Searching...   ",
+
+		regexsearch = False
+		if self.searchkey[0] == '%':
+			regexsearch = True
+			self.searchkey = self.searchkey[1:]
+		if self.searchkey[0] == '@':
+			match_category = 1
+			self.searchkey = self.searchkey[1:]
+		if regexsearch:
+			self.searchre=re.compile(self.searchkey,re.I)
+		else:
+			self.searchre=re.compile(re.escape(self.searchkey), re.I)
+		for package in self.portdb.cp_all():
+			self.spinner.update()
+
+			if match_category:
+				match_string  = package[:]
+			else:
+				match_string  = package.split("/")[-1]
+
+			masked=0
+			if self.searchre.search(match_string):
+				if not self.portdb.xmatch("match-visible", package):
+					masked=1
+				self.matches["pkg"].append([package,masked])
+			elif self.searchdesc: # DESCRIPTION searching
+				full_package = self.portdb.xmatch("bestmatch-visible", package)
+				if not full_package:
+					#no match found; we don't want to query description
+					full_package = portage.best(
+						self.portdb.xmatch("match-all", package))
+					if not full_package:
+						continue
+					else:
+						masked=1
+				try:
+					full_desc = self.portdb.aux_get(
+						full_package, ["DESCRIPTION"])[0]
+				except KeyError:
+					print "emerge: search: aux_get() failed, skipping"
+					continue
+				if self.searchre.search(full_desc):
+					self.matches["desc"].append([full_package,masked])
+		self.mlen=0
+		for mtype in self.matches.keys():
+			self.matches[mtype].sort()
+			self.mlen += len(self.matches[mtype])
+
+	def output(self):
+		"""Outputs the results of the search."""
+		print "\b\b  \n[ Results for search key : "+white(self.searchkey)+" ]"
+		print "[ Applications found : "+white(str(self.mlen))+" ]"
+		print " "
+		for mtype in self.matches.keys():
+			for match,masked in self.matches[mtype]:
+				if mtype=="pkg":
+					catpack=match
+					full_package = self.portdb.xmatch(
+						"bestmatch-visible", match)
+					if not full_package:
+						#no match found; we don't want to query description
+						masked=1
+						full_package = portage.best(
+							self.portdb.xmatch("match-all",match))
+				else:
+					full_package = match
+					match        = portage.pkgsplit(match)[0]
+
+				if full_package:
+					try:
+						desc, homepage, license = self.portdb.aux_get(
+							full_package, ["DESCRIPTION","HOMEPAGE","LICENSE"])
+					except KeyError:
+						print "emerge: search: aux_get() failed, skipping"
+						continue
+					if masked:
+						print green("*")+"  "+white(match)+" "+red("[ Masked ]")
+					else:
+						print green("*")+"  "+white(match)
+					myversion = self.getVersion(full_package, search.VERSION_RELEASE)
+
+					mysum = [0,0]
+					mycat = match.split("/")[0]
+					mypkg = match.split("/")[1]
+					mycpv = match + "-" + myversion
+					myebuild = self.portdb.findname(mycpv)
+					pkgdir = os.path.dirname(myebuild)
+					import portage_manifest
+					mf = portage_manifest.Manifest(
+						pkgdir, self.settings["DISTDIR"])
+					fetchlist = self.portdb.getfetchlist(mycpv,
+						mysettings=self.settings, all=True)[1]
+					try:
+						mysum[0] = mf.getDistfilesSize(fetchlist)
+						mystr = str(mysum[0]/1024)
+						mycount=len(mystr)
+						while (mycount > 3):
+							mycount-=3
+							mystr=mystr[:mycount]+","+mystr[mycount:]
+						mysum[0]=mystr+" kB"
+					except KeyError, e:
+						mysum[0] = "Unknown (missing digest for %s)" % str(e)
+
+					if self.verbose:
+						print "     ", darkgreen("Latest version available:"),myversion
+						print "     ", self.getInstallationStatus(mycat+'/'+mypkg)
+						print "     ", darkgreen("Size of files:"),mysum[0]
+						print "     ", darkgreen("Homepage:")+"     ",homepage
+						print "     ", darkgreen("Description:")+"  ",desc
+						print "     ", darkgreen("License:")+"      ",license
+						print
+		print
+	#
+	# private interface
+	#
+	def getInstallationStatus(self,package):
+		installed_package = self.vartree.dep_bestmatch(package)
+		result = ""
+		version = self.getVersion(installed_package,search.VERSION_RELEASE)
+		if len(version) > 0:
+			result = darkgreen("Latest version installed:")+" "+version
+		else:
+			result = darkgreen("Latest version installed:")+" [ Not Installed ]"
+		return result
+
+	def getVersion(self,full_package,detail):
+		if len(full_package) > 1:
+			package_parts = portage.catpkgsplit(full_package)
+			if detail == search.VERSION_RELEASE and package_parts[3] != 'r0':
+				result = package_parts[2]+ "-" + package_parts[3]
+			else:
+				result = package_parts[2]
+		else:
+			result = ""
+		return result
+
+
+#build our package digraph
+def getlist(settings, mode):
+	if mode=="system":
+		mylines = settings.packages
+	elif mode=="world":
+		try:
+			file_path = os.path.join(settings["ROOT"], portage.WORLD_FILE)
+			myfile = open(file_path, "r")
+			mylines = myfile.readlines()
+			myfile.close()
+		except (OSError, IOError), e:
+			if e.errno == errno.ENOENT:
+				portage.writemsg("\n!!! World file does not exist: '%s'\n" % file_path)
+				mylines=[]
+			else:
+				raise
+	mynewlines=[]
+	for x in mylines:
+		myline=" ".join(x.split())
+		if not len(myline):
+			continue
+		elif myline[0]=="#":
+			continue
+		elif mode=="system":
+			if myline[0]!="*":
+				continue
+			myline=myline[1:]
+		mynewlines.append(myline.strip())
+
+	return mynewlines
+
+def clean_world(vardb, cpv):
+	"""Remove a package from the world file when unmerged."""
+	world_filename = os.path.join(vardb.root, portage.WORLD_FILE)
+	worldlist = portage_util.grabfile(world_filename)
+	mykey = portage.cpv_getkey(cpv)
+	newworldlist = []
+	for x in worldlist:
+		if portage.dep_getkey(x) == mykey:
+			matches = vardb.match(x, use_cache=0)
+			if not matches:
+				#zap our world entry
+				pass
+			elif len(matches) == 1 and matches[0] == cpv:
+				#zap our world entry
+				pass
+			else:
+				#others are around; keep it.
+				newworldlist.append(x)
+		else:
+			#this doesn't match the package we're unmerging; keep it.
+			newworldlist.append(x)
+
+	portage_util.ensure_dirs(os.path.join(vardb.root, portage.PRIVATE_PATH),
+		gid=portage.portage_gid, mode=02770)
+	portage_util.write_atomic(world_filename, "\n".join(newworldlist))
+
+def genericdict(mylist):
+	mynewdict={}
+	for x in mylist:
+		mynewdict[portage.dep_getkey(x)]=x
+	return mynewdict
+
+def filter_iuse_defaults(iuse):
+	for flag in iuse:
+		if flag.startswith("+"):
+			yield flag[1:]
+		else:
+			yield flag
+
+class DepPriority(object):
+	"""
+		This class generates an integer priority level based of various
+		attributes of the dependency relationship.  Attributes can be assigned
+		at any time and the new integer value will be generated on calls to the
+		__int__() method.  Rich comparison operators are supported.
+
+		The boolean attributes that affect the integer value are "satisfied",
+		"buildtime", "runtime", and "system".  Various combinations of
+		attributes lead to the following priority levels:
+
+		Combination of properties    Priority level
+
+		not satisfied and buildtime     0
+		not satisfied and runtime      -1
+		satisfied and buildtime        -2
+		satisfied and runtime          -3
+		(none of the above)            -4
+
+		Several integer constants are defined for categorization of priority
+		levels:
+
+		MEDIUM   The upper boundary for medium dependencies.
+		SOFT     The upper boundary for soft dependencies.
+		MIN      The lower boundary for soft dependencies.
+	"""
+	__slots__ = ("__weakref__", "satisfied", "buildtime", "runtime")
+	MEDIUM = -1
+	SOFT   = -2
+	MIN    = -4
+	def __init__(self, **kwargs):
+		for myattr in self.__slots__:
+			if myattr == "__weakref__":
+				continue
+			myvalue = kwargs.get(myattr, False)
+			setattr(self, myattr, myvalue)
+	def __int__(self):
+		if not self.satisfied:
+			if self.buildtime:
+				return 0
+			if self.runtime:
+				return -1
+		if self.buildtime:
+			return -2
+		if self.runtime:
+			return -3
+		return -4
+	def __lt__(self, other):
+		return self.__int__() < other
+	def __le__(self, other):
+		return self.__int__() <= other
+	def __eq__(self, other):
+		return self.__int__() == other
+	def __ne__(self, other):
+		return self.__int__() != other
+	def __gt__(self, other):
+		return self.__int__() > other
+	def __ge__(self, other):
+		return self.__int__() >= other
+	def copy(self):
+		import copy
+		return copy.copy(self)
+	def __str__(self):
+		myvalue = self.__int__()
+		if myvalue > self.MEDIUM:
+			return "hard"
+		if myvalue > self.SOFT:
+			return "medium"
+		return "soft"
+
+class FakeVartree(portage.vartree):
+	"""This is implements an in-memory copy of a vartree instance that provides
+	all the interfaces required for use by the depgraph.  The vardb is locked
+	during the constructor call just long enough to read a copy of the
+	installed package information.  This allows the depgraph to do it's
+	dependency calculations without holding a lock on the vardb.  It also
+	allows things like vardb global updates to be done in memory so that the
+	user doesn't necessarily need write access to the vardb in cases where
+	global updates are necessary (updates are performed when necessary if there
+	is not a matching ebuild in the tree)."""
+	def __init__(self, real_vartree, portdb):
+		self.root = real_vartree.root
+		self.settings = real_vartree.settings
+		self.dbapi = portage.fakedbapi(settings=real_vartree.settings)
+		vdb_path = os.path.join(self.root, portage.VDB_PATH)
+		try:
+			# At least the parent needs to exist for the lock file.
+			portage_util.ensure_dirs(vdb_path)
+		except portage_exception.PortageException:
+			pass
+		vdb_lock = None
+		try:
+			if os.access(vdb_path, os.W_OK):
+				vdb_lock = portage_locks.lockdir(vdb_path)
+			mykeys = ["SLOT", "COUNTER", "PROVIDE", "USE", "IUSE",
+				"DEPEND", "RDEPEND", "PDEPEND"]
+			real_dbapi = real_vartree.dbapi
+			slot_counters = {}
+			for cpv in real_dbapi.cpv_all():
+				metadata = dict(izip(mykeys, real_dbapi.aux_get(cpv, mykeys)))
+				myslot = metadata["SLOT"]
+				mycp = portage.dep_getkey(cpv)
+				myslot_atom = "%s:%s" % (mycp, myslot)
+				try:
+					mycounter = long(metadata["COUNTER"])
+				except ValueError:
+					mycounter = 0
+					metadata["COUNTER"] = str(mycounter)
+				other_counter = slot_counters.get(myslot_atom, None)
+				if other_counter is not None:
+					if other_counter > mycounter:
+						continue
+				slot_counters[myslot_atom] = mycounter
+				self.dbapi.cpv_inject(cpv, metadata=metadata)
+			real_dbapi.flush_cache()
+		finally:
+			if vdb_lock:
+				portage_locks.unlockdir(vdb_lock)
+		# Populate the old-style virtuals using the cached values.
+		if not self.settings.treeVirtuals:
+			self.settings.treeVirtuals = portage_util.map_dictlist_vals(
+				portage.getCPFromCPV, self.get_all_provides())
+
+		# Intialize variables needed for lazy cache pulls of the live ebuild
+		# metadata.  This ensures that the vardb lock is released ASAP, without
+		# being delayed in case cache generation is triggered.
+		self._aux_get = self.dbapi.aux_get
+		self.dbapi.aux_get = self._aux_get_wrapper
+		self._aux_get_history = set()
+		self._portdb_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
+		self._portdb = portdb
+		self._global_updates = None
+
+	def _aux_get_wrapper(self, pkg, wants):
+		if pkg in self._aux_get_history:
+			return self._aux_get(pkg, wants)
+		self._aux_get_history.add(pkg)
+		try:
+			# Use the live ebuild metadata if possible.
+			live_metadata = dict(izip(self._portdb_keys,
+				self._portdb.aux_get(pkg, self._portdb_keys)))
+			self.dbapi.aux_update(pkg, live_metadata)
+		except (KeyError, portage_exception.PortageException):
+			if self._global_updates is None:
+				self._global_updates = \
+					grab_global_updates(self._portdb.porttree_root)
+			perform_global_updates(
+				pkg, self.dbapi, self._global_updates)
+		return self._aux_get(pkg, wants)
+
+def grab_global_updates(portdir):
+	from portage_update import grab_updates, parse_updates
+	updpath = os.path.join(portdir, "profiles", "updates")
+	try:
+		rawupdates = grab_updates(updpath)
+	except portage_exception.DirectoryNotFound:
+		rawupdates = []
+	upd_commands = []
+	for mykey, mystat, mycontent in rawupdates:
+		commands, errors = parse_updates(mycontent)
+		upd_commands.extend(commands)
+	return upd_commands
+
+def perform_global_updates(mycpv, mydb, mycommands):
+	from portage_update import update_dbentries
+	aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
+	aux_dict = dict(izip(aux_keys, mydb.aux_get(mycpv, aux_keys)))
+	updates = update_dbentries(mycommands, aux_dict)
+	if updates:
+		mydb.aux_update(mycpv, updates)
+
+class BlockerCache(DictMixin):
+	"""This caches blockers of installed packages so that dep_check does not
+	have to be done for every single installed package on every invocation of
+	emerge.  The cache is invalidated whenever it is detected that something
+	has changed that might alter the results of dep_check() calls:
+		1) the set of installed packages (including COUNTER) has changed
+		2) the old-style virtuals have changed
+	"""
+	class BlockerData(object):
+		def __init__(self, counter, atoms):
+			self.counter = counter
+			self.atoms = atoms
+
+	def __init__(self, myroot, vardb):
+		self._vardb = vardb
+		self._installed_pkgs = set(vardb.cpv_all())
+		self._virtuals = vardb.settings.getvirtuals()
+		self._cache_filename = os.path.join(myroot,
+			portage.CACHE_PATH.lstrip(os.path.sep), "vdb_blockers.pickle")
+		self._cache_version = "1"
+		self._cache_data = None
+		self._modified = False
+		self._load()
+
+	def _load(self):
+		try:
+			f = open(self._cache_filename)
+			mypickle = cPickle.Unpickler(f)
+			mypickle.find_global = None
+			self._cache_data = mypickle.load()
+			f.close()
+			del f
+		except (IOError, OSError, EOFError, cPickle.UnpicklingError):
+			pass
+		cache_valid = self._cache_data and \
+			isinstance(self._cache_data, dict) and \
+			self._cache_data.get("version") == self._cache_version and \
+			self._cache_data.get("virtuals") == self._virtuals and \
+			set(self._cache_data.get("blockers", [])) == self._installed_pkgs
+		if cache_valid:
+			for pkg in self._installed_pkgs:
+				if long(self._vardb.aux_get(pkg, ["COUNTER"])[0]) != \
+					self[pkg].counter:
+					cache_valid = False
+					break
+		if not cache_valid:
+			self._cache_data = {"version":self._cache_version}
+			self._cache_data["blockers"] = {}
+			self._cache_data["virtuals"] = self._virtuals
+		self._modified = False
+
+	def flush(self):
+		"""If the current user has permission and the internal blocker cache
+		been updated, save it to disk and mark it unmodified.  This is called
+		by emerge after it has proccessed blockers for all installed packages.
+		Currently, the cache is only written if the user has superuser
+		privileges (since that's required to obtain a lock), but all users
+		have read access and benefit from faster blocker lookups (as long as
+		the entire cache is still valid).  The cache is stored as a pickled
+		dict object with the following format:
+
+		{
+			version : "1",
+			"blockers" : {cpv1:(counter,(atom1, atom2...)), cpv2...},
+			"virtuals" : vardb.settings.getvirtuals()
+		}
+		"""
+		if self._modified and \
+			secpass >= 2:
+			try:
+				f = portage_util.atomic_ofstream(self._cache_filename)
+				cPickle.dump(self._cache_data, f, -1)
+				f.close()
+				portage_util.apply_secpass_permissions(
+					self._cache_filename, gid=portage.portage_gid, mode=0644)
+			except (IOError, OSError), e:
+				pass
+			self._modified = False
+
+	def __setitem__(self, cpv, blocker_data):
+		"""
+		Update the cache and mark it as modified for a future call to
+		self.flush().
+
+		@param cpv: Package for which to cache blockers.
+		@type cpv: String
+		@param blocker_data: An object with counter and atoms attributes.
+		@type blocker_data: BlockerData
+		"""
+		self._cache_data["blockers"][cpv] = \
+			(blocker_data.counter, blocker_data.atoms)
+		self._modified = True
+
+	def __getitem__(self, cpv):
+		"""
+		@rtype: BlockerData
+		@returns: An object with counter and atoms attributes.
+		"""
+		return self.BlockerData(*self._cache_data["blockers"][cpv])
+
+def show_invalid_depstring_notice(parent_node, depstring, error_msg):
+
+	from formatter import AbstractFormatter, DumbWriter
+	f = AbstractFormatter(DumbWriter(maxcol=72))
+
+	print "\n\n!!! Invalid or corrupt dependency specification: "
+	print
+	print error_msg
+	print
+	print parent_node
+	print
+	print depstring
+	print
+	p_type, p_root, p_key, p_status = parent_node
+	msg = []
+	if p_status == "nomerge":
+		category, pf = portage.catsplit(p_key)
+		pkg_location = os.path.join(p_root, portage.VDB_PATH, category, pf)
+		msg.append("Portage is unable to process the dependencies of the ")
+		msg.append("'%s' package. " % p_key)
+		msg.append("In order to correct this problem, the package ")
+		msg.append("should be uninstalled, reinstalled, or upgraded. ")
+		msg.append("As a temporary workaround, the --nodeps option can ")
+		msg.append("be used to ignore all dependencies.  For reference, ")
+		msg.append("the problematic dependencies can be found in the ")
+		msg.append("*DEPEND files located in '%s/'." % pkg_location)
+	else:
+		msg.append("This package can not be installed.  ")
+		msg.append("Please notify the '%s' package maintainer " % p_key)
+		msg.append("about this problem.")
+
+	for x in msg:
+		f.add_flowing_data(x)
+	f.end_paragraph(1)
+
+class depgraph:
+
+	pkg_tree_map = {
+		"ebuild":"porttree",
+		"binary":"bintree",
+		"installed":"vartree"}
+
+	def __init__(self, settings, trees, myopts, myparams, spinner):
+		self.settings = settings
+		self.target_root = settings["ROOT"]
+		self.myopts = myopts
+		self.myparams = myparams
+		self.edebug = 0
+		if settings.get("PORTAGE_DEBUG", "") == "1":
+			self.edebug = 1
+		self.spinner = spinner
+		self.pkgsettings = {}
+		# Maps cpv to digraph node for all nodes added to the graph.
+		self.pkg_node_map = {}
+		# Maps slot atom to digraph node for all nodes added to the graph.
+		self._slot_node_map = {}
+		self.mydbapi = {}
+		self._mydbapi_keys = ["SLOT", "DEPEND", "RDEPEND", "PDEPEND"]
+		self.useFlags = {}
+		self.trees = {}
+		for myroot in trees:
+			self.trees[myroot] = {}
+			for tree in ("porttree", "bintree"):
+				self.trees[myroot][tree] = trees[myroot][tree]
+			self.trees[myroot]["vartree"] = \
+				FakeVartree(trees[myroot]["vartree"],
+					trees[myroot]["porttree"].dbapi)
+			self.pkgsettings[myroot] = portage.config(
+				clone=self.trees[myroot]["vartree"].settings)
+			self.pkg_node_map[myroot] = {}
+			self._slot_node_map[myroot] = {}
+			vardb = self.trees[myroot]["vartree"].dbapi
+			# This fakedbapi instance will model the state that the vdb will
+			# have after new packages have been installed.
+			fakedb = portage.fakedbapi(settings=self.pkgsettings[myroot])
+			self.mydbapi[myroot] = fakedb
+			if "--nodeps" not in self.myopts and \
+				"--buildpkgonly" not in self.myopts:
+				# --nodeps bypasses this, since it isn't needed in this case
+				# and the cache pulls might trigger (slow) cache generation.
+				for pkg in vardb.cpv_all():
+					self.spinner.update()
+					fakedb.cpv_inject(pkg,
+						metadata=dict(izip(self._mydbapi_keys,
+						vardb.aux_get(pkg, self._mydbapi_keys))))
+			del vardb, fakedb
+			self.useFlags[myroot] = {}
+			if "--usepkg" in self.myopts:
+				self.trees[myroot]["bintree"].populate(
+					"--getbinpkg" in self.myopts,
+					"--getbinpkgonly" in self.myopts)
+		del trees
+
+		self.missingbins=[]
+		self.digraph=portage.digraph()
+		# Tracks simple parent/child relationships (PDEPEND relationships are
+		# not reversed).
+		self._parent_child_digraph = digraph()
+		self.orderedkeys=[]
+		self.outdatedpackages=[]
+		self.args_keys = []
+		self.blocker_digraph = digraph()
+		self.blocker_parents = {}
+		self._unresolved_blocker_parents = {}
+		self._slot_collision_info = []
+		# Slot collision nodes are not allowed to block other packages since
+		# blocker validation is only able to account for one package per slot.
+		self._slot_collision_nodes = set()
+		self._altlist_cache = {}
+		self._pprovided_args = []
+
+	def _show_slot_collision_notice(self, packages):
+		"""Show an informational message advising the user to mask one of the
+		the packages. In some cases it may be possible to resolve this
+		automatically, but support for backtracking (removal nodes that have
+		already been selected) will be required in order to handle all possible
+		cases."""
+
+		msg = []
+		msg.append("\n!!! Multiple versions within a single " + \
+			"package slot have been \n")
+		msg.append("!!! pulled into the dependency graph:\n\n")
+		for node, parents in packages:
+			msg.append(str(node))
+			if parents:
+				msg.append(" pulled in by\n")
+				for parent in parents:
+					msg.append("  ")
+					msg.append(str(parent))
+					msg.append("\n")
+			else:
+				msg.append(" (no parents)\n")
+			msg.append("\n")
+		sys.stderr.write("".join(msg))
+		sys.stderr.flush()
+
+		if "--quiet" in self.myopts:
+			return
+
+		msg = []
+		msg.append("It may be possible to solve this problem ")
+		msg.append("by using package.mask to prevent one of ")
+		msg.append("those packages from being selected. ")
+		msg.append("However, it is also possible that conflicting ")
+		msg.append("dependencies exist such that they are impossible to ")
+		msg.append("satisfy simultaneously.  If such a conflict exists in ")
+		msg.append("the dependencies of two different packages, then those ")
+		msg.append("packages can not be installed simultaneously.")
+
+		from formatter import AbstractFormatter, DumbWriter
+		f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
+		for x in msg:
+			f.add_flowing_data(x)
+		f.end_paragraph(1)
+
+		msg = []
+		msg.append("For more information, see MASKED PACKAGES ")
+		msg.append("section in the emerge man page or refer ")
+		msg.append("to the Gentoo Handbook.")
+		for x in msg:
+			f.add_flowing_data(x)
+		f.end_paragraph(1)
+		f.writer.flush()
+
+	def create(self, mybigkey, myparent=None, addme=1, myuse=None,
+		priority=DepPriority(), rev_dep=False, arg=None):
+		"""
+		Fills the digraph with nodes comprised of packages to merge.
+		mybigkey is the package spec of the package to merge.
+		myparent is the package depending on mybigkey ( or None )
+		addme = Should we add this package to the digraph or are we just looking at it's deps?
+			Think --onlydeps, we need to ignore packages in that case.
+		#stuff to add:
+		#SLOT-aware emerge
+		#IUSE-aware emerge -> USE DEP aware depgraph
+		#"no downgrade" emerge
+		"""
+		mytype, myroot, mykey = mybigkey
+		existing_node = None
+		if addme:
+			existing_node = self.pkg_node_map[myroot].get(mykey)
+		if existing_node:
+			self._parent_child_digraph.add(existing_node, myparent)
+			if existing_node != myparent:
+				# Refuse to make a node depend on itself so that the we don't
+				# don't create a bogus circular dependency in self.altlist().
+				if rev_dep and myparent:
+					self.digraph.addnode(myparent, existing_node,
+						priority=priority)
+				else:
+					self.digraph.addnode(existing_node, myparent,
+						priority=priority)
+			return 1
+		
+		if "--nodeps" not in self.myopts:
+			self.spinner.update()
+		if mytype == "blocks":
+			if myparent and \
+				"--buildpkgonly" not in self.myopts and \
+				"--nodeps" not in self.myopts and \
+				myparent not in self._slot_collision_nodes:
+				mybigkey[1] = myparent[1]
+				self.blocker_parents.setdefault(
+					tuple(mybigkey), set()).add(myparent)
+			return 1
+		if not arg and myroot == self.target_root:
+			arg = portage.best_match_to_list(mykey, self.args_keys)
+		# select the correct /var database that we'll be checking against
+		vardbapi = self.trees[myroot]["vartree"].dbapi
+		portdb = self.trees[myroot]["porttree"].dbapi
+		bindb = self.trees[myroot]["bintree"].dbapi
+		pkgsettings = self.pkgsettings[myroot]
+
+		# if the package is already on the system, we add a "nomerge"
+		# directive, otherwise we add a "merge" directive.
+
+		mydbapi = self.trees[myroot][self.pkg_tree_map[mytype]].dbapi
+
+		if myuse is None:
+			self.pkgsettings[myroot].setcpv(mykey, mydb=portdb)
+			myuse = self.pkgsettings[myroot]["USE"].split()
+
+		merging=1
+		if mytype == "installed":
+			merging = 0
+		if addme and mytype != "installed":
+		# this is where we add the node to the list of packages to merge
+			if "selective" in self.myparams or not arg:
+				if "empty" not in self.myparams and vardbapi.cpv_exists(mykey):
+					merging=0
+
+			""" If we aren't merging, perform the --newuse check.
+			    If the package has new iuse flags or different use flags then if
+			    --newuse is specified, we need to merge the package. """
+			if merging==0 and "--newuse" in self.myopts and \
+				vardbapi.cpv_exists(mykey):
+				pkgsettings.setcpv(mykey, mydb=mydbapi)
+				forced_flags = set()
+				forced_flags.update(pkgsettings.useforce)
+				forced_flags.update(pkgsettings.usemask)
+				old_use = vardbapi.aux_get(mykey, ["USE"])[0].split()
+				iuses = set(filter_iuse_defaults(
+					mydbapi.aux_get(mykey, ["IUSE"])[0].split()))
+				old_iuse = set(filter_iuse_defaults(
+					vardbapi.aux_get(mykey, ["IUSE"])[0].split()))
+				if iuses.symmetric_difference(
+					old_iuse).difference(forced_flags):
+					merging = 1
+				elif old_iuse.intersection(old_use) != \
+					iuses.intersection(myuse):
+					merging=1
+
+		if addme and merging == 1:
+			mybigkey.append("merge")
+		else:
+			mybigkey.append("nomerge")
+		jbigkey = tuple(mybigkey)
+
+		if addme:
+			metadata = dict(izip(self._mydbapi_keys,
+				mydbapi.aux_get(mykey, self._mydbapi_keys)))
+			if merging == 0 and vardbapi.cpv_exists(mykey) and \
+				mytype != "installed":
+				mybigkey[0] = "installed"
+				mydbapi = vardbapi
+				jbigkey = tuple(mybigkey)
+				metadata = dict(izip(self._mydbapi_keys,
+					mydbapi.aux_get(mykey, self._mydbapi_keys)))
+				myuse = mydbapi.aux_get(mykey, ["USE"])[0].split()
+			slot_atom = "%s:%s" % (portage.dep_getkey(mykey), metadata["SLOT"])
+			existing_node = self._slot_node_map[myroot].get(
+				slot_atom, None)
+			slot_collision = False
+			if existing_node:
+				e_type, myroot, e_cpv, e_status = existing_node
+				if mykey == e_cpv:
+					# The existing node can be reused.
+					self._parent_child_digraph.add(existing_node, myparent)
+					if rev_dep and myparent:
+						ptype, proot, pkey, pstatus = myparent
+						self.digraph.addnode(myparent, existing_node,
+							priority=priority)
+					else:
+						self.digraph.addnode(existing_node, myparent,
+							priority=priority)
+					return 1
+				else:
+					# A slot collision has occurred.  Sometimes this coincides
+					# with unresolvable blockers, so the slot collision will be
+					# shown later if there are no unresolvable blockers.
+					e_parents = self._parent_child_digraph.parent_nodes(
+						existing_node)
+					myparents = []
+					if myparent:
+						myparents.append(myparent)
+					self._slot_collision_info.append(
+						((jbigkey, myparents), (existing_node, e_parents)))
+					self._slot_collision_nodes.add(jbigkey)
+					slot_collision = True
+
+			if slot_collision:
+				# Now add this node to the graph so that self.display()
+				# can show use flags and --tree output.  This node is
+				# only being partially added to the graph.  It must not be
+				# allowed to interfere with the other nodes that have been
+				# added.  Do not overwrite data for existing nodes in
+				# self.pkg_node_map and self.mydbapi since that data will
+				# be used for blocker validation.
+				self.pkg_node_map[myroot].setdefault(mykey, jbigkey)
+				self.useFlags[myroot].setdefault(mykey, myuse)
+				# Even though the graph is now invalid, continue to process
+				# dependencies so that things like --fetchonly can still
+				# function despite collisions.
+			else:
+				self.mydbapi[myroot].cpv_inject(mykey, metadata=metadata)
+				self._slot_node_map[myroot][slot_atom] = jbigkey
+				self.pkg_node_map[myroot][mykey] = jbigkey
+				self.useFlags[myroot][mykey] = myuse
+
+			if rev_dep and myparent:
+				self.digraph.addnode(myparent, jbigkey,
+					priority=priority)
+			else:
+				self.digraph.addnode(jbigkey, myparent,
+					priority=priority)
+
+		# Do this even when addme is False (--onlydeps) so that the
+		# parent/child relationship is always known in case
+		# self._show_slot_collision_notice() needs to be called later.
+		self._parent_child_digraph.add(jbigkey, myparent)
+
+		""" This section determines whether we go deeper into dependencies or not.
+		    We want to go deeper on a few occasions:
+		    Installing package A, we need to make sure package A's deps are met.
+		    emerge --deep <pkgspec>; we need to recursively check dependencies of pkgspec
+		    If we are in --nodeps (no recursion) mode, we obviously only check 1 level of dependencies.
+		"""
+		if "deep" not in self.myparams and not merging and \
+			not ("--update" in self.myopts and arg and merging):
+			return 1
+		elif "recurse" not in self.myparams:
+			return 1
+
+		""" Check DEPEND/RDEPEND/PDEPEND/SLOT
+		Pull from bintree if it's binary package, porttree if it's ebuild.
+		Binpkg's can be either remote or local. """
+
+		edepend={}
+		depkeys = ["DEPEND","RDEPEND","PDEPEND"]
+		depvalues = mydbapi.aux_get(mykey, depkeys)
+		for i in xrange(len(depkeys)):
+			edepend[depkeys[i]] = depvalues[i]
+
+		if mytype == "ebuild":
+			if "--buildpkgonly" in self.myopts:
+				edepend["RDEPEND"] = ""
+				edepend["PDEPEND"] = ""
+		if not (arg and "--onlydeps" in self.myopts and \
+			mytype == "ebuild") and \
+			self.myopts.get("--with-bdeps", "n") == "n" and \
+			(mytype == "binary" or mybigkey[3] == "nomerge"):
+			edepend["DEPEND"] = ""
+
+		""" We have retrieve the dependency information, now we need to recursively
+		    process them.  DEPEND gets processed for root = "/", {R,P}DEPEND in myroot. """
+		
+		mp = tuple(mybigkey)
+
+		try:
+			if not self.select_dep("/", edepend["DEPEND"], myparent=mp,
+				myuse=myuse, priority=DepPriority(buildtime=True),
+				parent_arg=arg):
+				return 0
+			"""RDEPEND is soft by definition.  However, in order to ensure
+			correct merge order, we make it a hard dependency.  Otherwise, a
+			build time dependency might not be usable due to it's run time
+			dependencies not being installed yet.
+			"""
+			if not self.select_dep(myroot,edepend["RDEPEND"], myparent=mp,
+				myuse=myuse, priority=DepPriority(runtime=True),
+				parent_arg=arg):
+				return 0
+			if edepend.has_key("PDEPEND") and edepend["PDEPEND"]:
+				# Post Depend -- Add to the list without a parent, as it depends
+				# on a package being present AND must be built after that package.
+				if not self.select_dep(myroot, edepend["PDEPEND"], myparent=mp,
+					myuse=myuse, priority=DepPriority(), rev_deps=True,
+					parent_arg=arg):
+					return 0
+		except ValueError, e:
+			pkgs = e.args[0]
+			portage.writemsg("\n\n!!! An atom in the dependencies " + \
+				"is not fully-qualified. Multiple matches:\n\n", noiselevel=-1)
+			for cpv in pkgs:
+				portage.writemsg("    %s\n" % cpv, noiselevel=-1)
+			portage.writemsg("\n", noiselevel=-1)
+			if mytype == "binary":
+				portage.writemsg(
+					"!!! This binary package cannot be installed: '%s'\n" % \
+					mykey, noiselevel=-1)
+			elif mytype == "ebuild":
+				myebuild, mylocation = portdb.findname2(mykey)
+				portage.writemsg("!!! This ebuild cannot be installed: " + \
+					"'%s'\n" % myebuild, noiselevel=-1)
+			portage.writemsg("!!! Please notify the package maintainer " + \
+				"that atoms must be fully-qualified.\n", noiselevel=-1)
+			return 0
+		return 1
+
+	def select_files(self,myfiles):
+		"given a list of .tbz2s, .ebuilds and deps, create the appropriate depgraph and return a favorite list"
+		myfavorites=[]
+		myroot = self.target_root
+		portdb = self.trees[myroot]["porttree"].dbapi
+		bindb = self.trees[myroot]["bintree"].dbapi
+		pkgsettings = self.pkgsettings[myroot]
+		arg_atoms = []
+		def visible(mylist):
+			matches = portdb.gvisible(portdb.visible(mylist))
+			return [x for x in mylist \
+				if x in matches or not portdb.cpv_exists(x)]
+		for x in myfiles:
+			ext = os.path.splitext(x)[1]
+			if ext==".tbz2":
+				if not os.path.exists(x):
+					if os.path.exists(
+						os.path.join(pkgsettings["PKGDIR"], "All", x)):
+						x = os.path.join(pkgsettings["PKGDIR"], "All", x)
+					elif os.path.exists(
+						os.path.join(pkgsettings["PKGDIR"], x)):
+						x = os.path.join(pkgsettings["PKGDIR"], x)
+					else:
+						print "\n\n!!! Binary package '"+str(x)+"' does not exist."
+						print "!!! Please ensure the tbz2 exists as specified.\n"
+						sys.exit(1)
+				mytbz2=xpak.tbz2(x)
+				mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.splitext(os.path.basename(x))[0]
+				if os.path.realpath(x) != \
+					os.path.realpath(self.trees[myroot]["bintree"].getname(mykey)):
+					print colorize("BAD", "\n*** You need to adjust PKGDIR to emerge this package.\n")
+					sys.exit(1)
+				if not self.create(["binary", myroot, mykey],
+					None, "--onlydeps" not in self.myopts):
+					return (0,myfavorites)
+				elif not "--oneshot" in self.myopts:
+					myfavorites.append(mykey)
+			elif ext==".ebuild":
+				x = os.path.realpath(x)
+				mykey=os.path.basename(os.path.normpath(x+"/../.."))+"/"+os.path.splitext(os.path.basename(x))[0]
+				ebuild_path = portdb.findname(mykey)
+				if ebuild_path:
+					if os.path.realpath(ebuild_path) != x:
+						print colorize("BAD", "\n*** You need to adjust PORTDIR or PORTDIR_OVERLAY to emerge this package.\n")
+						sys.exit(1)
+					if mykey not in portdb.xmatch(
+						"match-visible", portage.dep_getkey(mykey)):
+						print colorize("BAD", "\n*** You are emerging a masked package. It is MUCH better to use")
+						print colorize("BAD", "*** /etc/portage/package.* to accomplish this. See portage(5) man")
+						print colorize("BAD", "*** page for details.")
+						countdown(int(self.settings["EMERGE_WARNING_DELAY"]),
+							"Continuing...")
+				else:
+					raise portage_exception.PackageNotFound(
+						"%s is not in a valid portage tree hierarchy or does not exist" % x)
+				if not self.create(["ebuild", myroot, mykey],
+					None, "--onlydeps" not in self.myopts):
+					return (0,myfavorites)
+				elif not "--oneshot" in self.myopts:
+					myfavorites.append(mykey)
+			else:
+				if not is_valid_package_atom(x):
+					portage.writemsg("\n\n!!! '%s' is not a valid package atom.\n" % x,
+						noiselevel=-1)
+					portage.writemsg("!!! Please check ebuild(5) for full details.\n")
+					portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
+					return (0,[])
+				try:
+					mykey = None
+					if "--usepkg" in self.myopts:
+						mykey = portage.dep_expand(x, mydb=bindb,
+							settings=pkgsettings)
+					if (mykey and not mykey.startswith("null/")) or \
+						"--usepkgonly" in self.myopts:
+						arg_atoms.append((x, mykey))
+						continue
+
+					mykey = portage.dep_expand(x,
+						mydb=portdb, settings=pkgsettings)
+					arg_atoms.append((x, mykey))
+				except ValueError, errpkgs:
+					print "\n\n!!! The short ebuild name \"" + x + "\" is ambiguous.  Please specify"
+					print "!!! one of the following fully-qualified ebuild names instead:\n"
+					for i in errpkgs[0]:
+						print "    " + green(i)
+					print
+					sys.exit(1)
+
+		if "--update" in self.myopts:
+			"""Make sure all installed slots are updated when possible. Do this
+			with --emptytree also, to ensure that all slots are remerged."""
+			vardb = self.trees[self.target_root]["vartree"].dbapi
+			greedy_atoms = []
+			for myarg, myatom in arg_atoms:
+				greedy_atoms.append((myarg, myatom))
+				myslots = set()
+				for cpv in vardb.match(myatom):
+					myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
+				if myslots:
+					best_pkgs = []
+					if "--usepkg" in self.myopts:
+						mymatches = bindb.match(myatom)
+						if "--usepkgonly" not in self.myopts:
+							mymatches = visible(mymatches)
+						best_pkg = portage.best(mymatches)
+						if best_pkg:
+							best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
+							best_pkgs.append(("binary", best_pkg, best_slot))
+					if "--usepkgonly" not in self.myopts:
+						best_pkg = portage.best(portdb.match(myatom))
+						if best_pkg:
+							best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
+							best_pkgs.append(("ebuild", best_pkg, best_slot))
+					if best_pkgs:
+						best_pkg = portage.best([x[1] for x in best_pkgs])
+						best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
+						best_slot = best_pkgs[0][2]
+						myslots.add(best_slot)
+				if len(myslots) > 1:
+					for myslot in myslots:
+						myslot_atom = "%s:%s" % \
+							(portage.dep_getkey(myatom), myslot)
+						available = False
+						if "--usepkgonly" not in self.myopts and \
+							self.trees[self.target_root][
+							"porttree"].dbapi.match(myslot_atom):
+							available = True
+						elif "--usepkg" in self.myopts:
+							mymatches = bindb.match(myslot_atom)
+							if "--usepkgonly" not in self.myopts:
+								mymatches = visible(mymatches)
+							if mymatches:
+								available = True
+						if available:
+							greedy_atoms.append((myarg, myslot_atom))
+			arg_atoms = greedy_atoms
+
+		""" These are used inside self.create() in order to ensure packages
+		that happen to match arguments are not incorrectly marked as nomerge."""
+		self.args_keys = [x[1] for x in arg_atoms]
+		for myarg, myatom in arg_atoms:
+				try:
+					self.mysd = self.select_dep(myroot, myatom, arg=myarg)
+				except portage_exception.MissingSignature, e:
+					portage.writemsg("\n\n!!! A missing gpg signature is preventing portage from calculating the\n")
+					portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
+					portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
+					portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
+					portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
+					sys.exit(1)
+				except portage_exception.InvalidSignature, e:
+					portage.writemsg("\n\n!!! An invalid gpg signature is preventing portage from calculating the\n")
+					portage.writemsg("!!! required dependencies. This is a security feature enabled by the admin\n")
+					portage.writemsg("!!! to aid in the detection of malicious intent.\n\n")
+					portage.writemsg("!!! THIS IS A POSSIBLE INDICATION OF TAMPERED FILES -- CHECK CAREFULLY.\n")
+					portage.writemsg("!!! Affected file: %s\n" % (e), noiselevel=-1)
+					sys.exit(1)
+				except SystemExit, e:
+					raise # Needed else can't exit
+				except Exception, e:
+					print >> sys.stderr, "\n\n!!! Problem in '%s' dependencies." % mykey
+					print >> sys.stderr, "!!!", str(e), getattr(e, "__module__", None)
+					raise
+
+				if not self.mysd:
+					return (0,myfavorites)
+				elif not "--oneshot" in self.myopts:
+					mykey = portage.dep_getkey(myatom)
+					if mykey not in myfavorites:
+						myfavorites.append(mykey)
+
+		missing=0
+		if "--usepkgonly" in self.myopts:
+			for xs in self.digraph.all_nodes():
+				if len(xs) >= 4 and xs[0] != "binary" and xs[3] == "merge":
+					if missing == 0:
+						print
+					missing += 1
+					print "Missing binary for:",xs[2]
+
+		if not self.validate_blockers():
+			return False, myfavorites
+		
+		# We're true here unless we are missing binaries.
+		return (not missing,myfavorites)
+
+	def select_dep(self, myroot, depstring, myparent=None, arg=None,
+		myuse=None, raise_on_missing=False, priority=DepPriority(),
+		rev_deps=False, parent_arg=None):
+		""" Given a depstring, create the depgraph such that all dependencies are satisfied.
+		    myroot = $ROOT from environment, where {R,P}DEPENDs are merged to.
+		    myparent = the node whose depstring is being passed in
+		    arg = package was specified on the command line, merge even if it's already installed
+		    myuse = USE flags at present
+		    raise_on_missing = Given that the depgraph is not proper, raise an exception if true
+		    else continue trying.
+		    return 1 on success, 0 for failure
+		"""
+
+		portdb = self.trees[myroot]["porttree"].dbapi
+		bindb  = self.trees[myroot]["bintree"].dbapi
+		vardb  = self.trees[myroot]["vartree"].dbapi
+		pkgsettings = self.pkgsettings[myroot]
+		if myparent:
+			p_type, p_root, p_key, p_status = myparent
+
+		if "--debug" in self.myopts:
+			print
+			print "Parent:   ",myparent
+			print "Depstring:",depstring
+			if rev_deps:
+				print "Reverse:", rev_deps
+			print "Priority:", priority
+
+		#processing dependencies
+		""" Call portage.dep_check to evaluate the use? conditionals and make sure all
+		dependencies are satisfiable. """
+		if arg:
+			mymerge = [depstring]
+			pprovided = pkgsettings.pprovideddict.get(
+				portage.dep_getkey(depstring))
+			if pprovided and portage.match_from_list(depstring, pprovided):
+				mymerge = []
+		else:
+			try:
+				if myparent and p_status == "nomerge":
+					portage_dep._dep_check_strict = False
+				mycheck = portage.dep_check(depstring, None,
+					pkgsettings, myuse=myuse,
+					use_binaries=("--usepkgonly" in self.myopts),
+					myroot=myroot, trees=self.trees)
+			finally:
+				portage_dep._dep_check_strict = True
+
+			if not mycheck[0]:
+				if myparent:
+					show_invalid_depstring_notice(
+						myparent, depstring, mycheck[1])
+				else:
+					sys.stderr.write("\n%s\n%s\n" % (depstring, mycheck[1]))
+				return 0
+			mymerge = mycheck[1]
+
+		if not mymerge and arg and \
+			portage.best_match_to_list(depstring, self.args_keys):
+			# A provided package has been specified on the command line.  The
+			# package will not be merged and a warning will be displayed.
+			self._pprovided_args.append(arg)
+
+		if myparent:
+			# The parent is added after it's own dep_check call so that it
+			# isn't allowed to satisfy a direct bootstrap dependency on itself
+			# via an old-style virtual.  This isn't a problem with new-style
+			# virtuals, which are preferenced in dep_zapdeps by looking only at
+			# the depstring, vdb, and available packages.
+
+			p_type, p_root, p_key, p_status = myparent
+			if p_status == "merge":
+				# Update old-style virtuals if this package provides any.
+				# These are needed for dep_virtual calls inside dep_check.
+				p_db = self.trees[p_root][self.pkg_tree_map[p_type]].dbapi
+				try:
+					self.pkgsettings[p_root].setinst(p_key, p_db)
+				except portage_exception.InvalidDependString, e:
+					provide = p_db.aux_get(p_key, ["PROVIDE"])[0]
+					show_invalid_depstring_notice(myparent, provide, str(e))
+					del e
+					return 0
+
+		if "--debug" in self.myopts:
+			print "Candidates:",mymerge
+		for x in mymerge:
+			selected_pkg = None
+			if x[0]=="!":
+				selected_pkg = ["blocks", myroot, x[1:], None]
+			else:
+				#We are not processing a blocker but a normal dependency
+				if myparent:
+					"""In some cases, dep_check will return deps that shouldn't
+					be proccessed any further, so they are identified and
+					discarded here."""
+					if "empty" not in self.myparams and \
+						"deep" not in self.myparams and \
+						not ("--update" in self.myopts and parent_arg) and \
+						vardb.match(x):
+						continue
+
+				# List of acceptable packages, ordered by type preference.
+				matched_packages = []
+				myeb_matches = portdb.xmatch("match-visible", x)
+				myeb = None
+				if "--usepkgonly" not in self.myopts:
+					myeb = portage.best(myeb_matches)
+
+				myeb_pkg=None
+				if "--usepkg" in self.myopts:
+					# The next line assumes the binarytree has been populated.
+					# XXX: Need to work out how we use the binary tree with roots.
+					myeb_pkg_matches = bindb.match(x)
+					if "--usepkgonly" not in self.myopts:
+						# Remove any binary package entries that are masked in the portage tree (#55871)
+						myeb_pkg_matches = [pkg for pkg in myeb_pkg_matches \
+							if pkg in myeb_matches or  \
+							not portdb.cpv_exists(pkg)]
+					if myeb_pkg_matches:
+						myeb_pkg = portage.best(myeb_pkg_matches)
+
+				if myeb_pkg and "--newuse" in self.myopts:
+					iuses = set(filter_iuse_defaults(
+						bindb.aux_get(myeb_pkg, ["IUSE"])[0].split()))
+					old_use = bindb.aux_get(myeb_pkg, ["USE"])[0].split()
+					mydb = None
+					if "--usepkgonly" not in self.myopts and myeb:
+						mydb = portdb
+					if myeb:
+						pkgsettings.setcpv(myeb, mydb=mydb)
+					else:
+						pkgsettings.setcpv(myeb_pkg, mydb=mydb)
+					now_use = pkgsettings["USE"].split()
+					forced_flags = set()
+					forced_flags.update(pkgsettings.useforce)
+					forced_flags.update(pkgsettings.usemask)
+					cur_iuse = iuses
+					if "--usepkgonly" not in self.myopts and myeb:
+						cur_iuse = set(filter_iuse_defaults(
+							portdb.aux_get(myeb, ["IUSE"])[0].split()))
+					if iuses.symmetric_difference(
+						cur_iuse).difference(forced_flags):
+						myeb_pkg = None
+					elif iuses.intersection(old_use) != \
+						cur_iuse.intersection(now_use):
+						myeb_pkg = None
+				if myeb_pkg:
+					binpkguseflags = \
+						self.trees[myroot]["bintree"].dbapi.aux_get(
+							myeb_pkg, ["USE"])[0].split()
+					matched_packages.append(
+						["binary", myroot, myeb_pkg, binpkguseflags])
+
+				if "--usepkgonly" not in self.myopts and myeb_matches:
+					matched_packages.append(
+						["ebuild", myroot, myeb, None])
+
+				if not matched_packages and \
+					not (arg and "selective" not in self.myparams):
+					"""Fall back to the installed package database.  This is a
+					last resort because the metadata tends to diverge from that
+					of the ebuild in the tree."""
+					myeb_inst_matches = vardb.match(x)
+					if "--usepkgonly" not in self.myopts:
+						""" TODO: Improve masking check for installed and
+						binary packages. bug #149816"""
+						myeb_inst_matches = [pkg for pkg in myeb_inst_matches \
+							if not portdb.cpv_exists(pkg)]
+					myeb_inst = None
+					if myeb_inst_matches:
+						myeb_inst = portage.best(myeb_inst_matches)
+					if myeb_inst:
+						binpkguseflags = vardb.aux_get(
+							myeb_inst, ["USE"])[0].split()
+						matched_packages.append(
+							["installed", myroot, myeb_inst, binpkguseflags])
+
+				if not matched_packages:
+					if raise_on_missing:
+						raise ValueError
+					if not arg:
+						xinfo='"'+x+'"'
+					else:
+						xinfo='"'+arg+'"'
+					if myparent:
+						xfrom = '(dependency required by '+ \
+							green('"%s"' % myparent[2]) + \
+							red(' [%s]' % myparent[0]) + ')'
+					alleb = portdb.xmatch("match-all", x)
+					if alleb:
+						if "--usepkgonly" not in self.myopts:
+							print "\n!!! "+red("All ebuilds that could satisfy ")+green(xinfo)+red(" have been masked.")
+							print "!!! One of the following masked packages is required to complete your request:"
+							oldcomment = ""
+							for p in alleb:
+								mreasons = portage.getmaskingstatus(p,
+									settings=pkgsettings, portdb=portdb)
+								print "- "+p+" (masked by: "+", ".join(mreasons)+")"
+								comment = portage.getmaskingreason(p,
+									settings=pkgsettings, portdb=portdb)
+								if comment and comment != oldcomment:
+									print comment
+									oldcomment = comment
+							print
+							print "For more information, see MASKED PACKAGES section in the emerge man page or "
+							print "refer to the Gentoo Handbook."
+						else:
+							print "\n!!! "+red("There are no packages available to satisfy: ")+green(xinfo)
+							print "!!! Either add a suitable binary package or compile from an ebuild."
+					else:
+						print "\nemerge: there are no ebuilds to satisfy "+green(xinfo)+"."
+					if myparent:
+						print xfrom
+					print
+					return 0
+
+				if "--debug" in self.myopts:
+					for pkg in matched_packages:
+						print (pkg[0] + ":").rjust(10), pkg[2]
+
+				if len(matched_packages) > 1:
+					bestmatch = portage.best(
+						[pkg[2] for pkg in matched_packages])
+					matched_packages = [pkg for pkg in matched_packages \
+						if pkg[2] == bestmatch]
+
+				# ordered by type preference ("ebuild" type is the last resort)
+				selected_pkg =  matched_packages[0]
+				pkgtype, myroot, mycpv, myuse = selected_pkg
+				mydbapi = self.trees[myroot][self.pkg_tree_map[pkgtype]].dbapi
+				slot_atom = "%s:%s" % (portage.dep_getkey(mycpv),
+					mydbapi.aux_get(mycpv, ["SLOT"])[0])
+				existing_node = self._slot_node_map[myroot].get(
+					slot_atom, None)
+				if existing_node:
+					e_type, myroot, e_cpv, e_status = existing_node
+					if portage.match_from_list(x, [e_cpv]):
+						# The existing node can be reused.
+						selected_pkg = [e_type, myroot, e_cpv,
+							self.useFlags[myroot][e_cpv]]
+
+			if myparent:
+				#we are a dependency, so we want to be unconditionally added
+				mypriority = priority.copy()
+				if vardb.match(x):
+					mypriority.satisfied = True
+				if not self.create(selected_pkg[0:3], myparent,
+					myuse=selected_pkg[-1], priority=mypriority,
+					rev_dep=rev_deps, arg=arg):
+					return 0
+			else:
+				#if mysource is not set, then we are a command-line dependency and should not be added
+				#if --onlydeps is specified.
+				if not self.create(selected_pkg[0:3], myparent,
+					addme=("--onlydeps" not in self.myopts),
+					myuse=selected_pkg[-1], rev_dep=rev_deps, arg=arg):
+					return 0
+
+		if "--debug" in self.myopts:
+			print "Exiting...",myparent
+		return 1
+
+	def validate_blockers(self):
+		"""Remove any blockers from the digraph that do not match any of the
+		packages within the graph.  If necessary, create hard deps to ensure
+		correct merge order such that mutually blocking packages are never
+		installed simultaneously."""
+
+		if "--buildpkgonly" in self.myopts or \
+			"--nodeps" in self.myopts:
+			return True
+
+		modified_slots = {}
+		for myroot in self.trees:
+			myslots = {}
+			modified_slots[myroot] = myslots
+			final_db = self.mydbapi[myroot]
+			slot_node_map = self._slot_node_map[myroot]
+			for slot_atom, mynode in slot_node_map.iteritems():
+				mytype, myroot, mycpv, mystatus = mynode
+				if mystatus == "merge":
+					myslots[slot_atom] = mycpv
+
+		#if "deep" in self.myparams:
+		if True:
+			# Pull in blockers from all installed packages that haven't already
+			# been pulled into the depgraph.  This is not enabled by default
+			# due to the performance penalty that is incurred by all the
+			# additional dep_check calls that are required.
+
+			# Optimization hack for dep_check calls that minimizes the
+			# available matches by replacing the portdb with a fakedbapi
+			# instance.
+			class FakePortageTree(object):
+				def __init__(self, mydb):
+					self.dbapi = mydb
+			dep_check_trees = {}
+			for myroot in self.trees:
+				dep_check_trees[myroot] = self.trees[myroot].copy()
+				dep_check_trees[myroot]["porttree"] = \
+					FakePortageTree(self.mydbapi[myroot])
+
+			dep_keys = ["DEPEND","RDEPEND","PDEPEND"]
+			for myroot in self.trees:
+				pkg_node_map = self.pkg_node_map[myroot]
+				vardb = self.trees[myroot]["vartree"].dbapi
+				portdb = self.trees[myroot]["porttree"].dbapi
+				pkgsettings = self.pkgsettings[myroot]
+				final_db = self.mydbapi[myroot]
+				cpv_all_installed = self.trees[myroot]["vartree"].dbapi.cpv_all()
+				blocker_cache = BlockerCache(myroot, vardb)
+				for pkg in cpv_all_installed:
+					blocker_atoms = None
+					matching_node = pkg_node_map.get(pkg, None)
+					if matching_node and \
+						matching_node[3] == "nomerge":
+						continue
+					# If this node has any blockers, create a "nomerge"
+					# node for it so that they can be enforced.
+					self.spinner.update()
+					blocker_data = blocker_cache.get(pkg)
+					if blocker_data:
+						blocker_atoms = blocker_data.atoms
+					else:
+						dep_vals = vardb.aux_get(pkg, dep_keys)
+						myuse = vardb.aux_get(pkg, ["USE"])[0].split()
+						depstr = " ".join(dep_vals)
+						# It is crucial to pass in final_db here in order to
+						# optimize dep_check calls by eliminating atoms via
+						# dep_wordreduce and dep_eval calls.
+						try:
+							portage_dep._dep_check_strict = False
+							try:
+								success, atoms = portage.dep_check(depstr,
+									final_db, pkgsettings, myuse=myuse,
+									trees=dep_check_trees, myroot=myroot)
+							except Exception, e:
+								if isinstance(e, SystemExit):
+									raise
+								# This is helpful, for example, if a ValueError
+								# is thrown from cpv_expand due to multiple
+								# matches (this can happen if an atom lacks a
+								# category).
+								show_invalid_depstring_notice(
+									("installed", myroot, pkg, "nomerge"),
+									depstr, str(e))
+								del e
+								raise
+						finally:
+							portage_dep._dep_check_strict = True
+						if not success:
+							slot_atom = "%s:%s" % (portage.dep_getkey(pkg),
+								vardb.aux_get(pkg, ["SLOT"])[0])
+							if slot_atom in modified_slots[myroot]:
+								# This package is being replaced anyway, so
+								# ignore invalid dependencies so as not to
+								# annoy the user too much (otherwise they'd be
+								# forced to manually unmerge it first).
+								continue
+							show_invalid_depstring_notice(
+								("installed", myroot, pkg, "nomerge"),
+								depstr, atoms)
+							return False
+						blocker_atoms = [myatom for myatom in atoms \
+							if myatom.startswith("!")]
+						counter = long(vardb.aux_get(pkg, ["COUNTER"])[0])
+						blocker_cache[pkg] = \
+							blocker_cache.BlockerData(counter, blocker_atoms)
+					if blocker_atoms:
+						# Don't store this parent in pkg_node_map, because it's
+						# not needed there and it might overwrite a "merge"
+						# node with the same cpv.
+						myparent = ("installed", myroot, pkg, "nomerge")
+						for myatom in blocker_atoms:
+							blocker = ("blocks", myroot, myatom[1:])
+							myparents = \
+								self.blocker_parents.get(blocker, None)
+							if not myparents:
+								myparents = set()
+								self.blocker_parents[blocker] = myparents
+							myparents.add(myparent)
+				blocker_cache.flush()
+				del blocker_cache
+
+		for blocker in self.blocker_parents.keys():
+			mytype, myroot, mydep = blocker
+			initial_db = self.trees[myroot]["vartree"].dbapi
+			final_db = self.mydbapi[myroot]
+			blocked_initial = initial_db.match(mydep)
+			blocked_final = final_db.match(mydep)
+			if not blocked_initial and not blocked_final:
+				del self.blocker_parents[blocker]
+				continue
+			blocked_slots_initial = {}
+			blocked_slots_final = {}
+			for cpv in blocked_initial:
+				blocked_slots_initial[cpv] = \
+					"%s:%s" % (portage.dep_getkey(cpv),
+						initial_db.aux_get(cpv, ["SLOT"])[0])
+			for cpv in blocked_final:
+				blocked_slots_final[cpv] = \
+					"%s:%s" % (portage.dep_getkey(cpv),
+						final_db.aux_get(cpv, ["SLOT"])[0])
+			for parent in list(self.blocker_parents[blocker]):
+				ptype, proot, pcpv, pstatus = parent
+				pdbapi = self.trees[proot][self.pkg_tree_map[ptype]].dbapi
+				pslot = pdbapi.aux_get(pcpv, ["SLOT"])[0]
+				pslot_atom = "%s:%s" % (portage.dep_getkey(pcpv), pslot)
+				parent_static = pslot_atom not in modified_slots[proot]
+				unresolved_blocks = False
+				depends_on_order = set()
+				for cpv in blocked_initial:
+					slot_atom = blocked_slots_initial[cpv]
+					if slot_atom == pslot_atom:
+						# The parent blocks an initial package in the same
+						# slot as itself.  The merge/nomerge status of neither
+						# node matters.  In any case, this particular block is
+						# automatically resolved.
+						continue
+					if parent_static and \
+						slot_atom not in modified_slots[myroot]:
+						# This blocker will be handled the next time that a
+						# merge of either package is triggered.
+						continue
+					if pstatus == "merge" and \
+						slot_atom in modified_slots[myroot]:
+						replacement = final_db.match(slot_atom)
+						if replacement:
+							if not portage.match_from_list(mydep, replacement):
+								# Apparently a replacement may be able to
+								# invalidate this block.
+								replacement_node = \
+									self.pkg_node_map[proot][replacement[0]]
+								depends_on_order.add((replacement_node, parent))
+								continue
+					# None of the above blocker resolutions techniques apply,
+					# so apparently this one is unresolvable.
+					unresolved_blocks = True
+				for cpv in blocked_final:
+					slot_atom = blocked_slots_final[cpv]
+					if slot_atom == pslot_atom:
+						# The parent blocks itself, so the merge order does not
+						# need to be enforced.
+						continue
+					if parent_static and \
+						slot_atom not in modified_slots[myroot]:
+						# This blocker will be handled the next time that a
+						# merge of either package is triggered.
+						continue
+					if not parent_static and pstatus == "nomerge" and \
+						slot_atom in modified_slots[myroot]:
+						replacement = final_db.match(pslot_atom)
+						if replacement:
+							replacement_node = \
+								self.pkg_node_map[proot][replacement[0]]
+							if replacement_node not in \
+								self.blocker_parents[blocker]:
+								# Apparently a replacement may be able to
+								# invalidate this block.
+								blocked_node = self.pkg_node_map[proot][cpv]
+								depends_on_order.add(
+									(replacement_node, blocked_node))
+								continue
+					# None of the above blocker resolutions techniques apply,
+					# so apparently this one is unresolvable.
+					unresolved_blocks = True
+				if not unresolved_blocks and depends_on_order:
+					for node, pnode in depends_on_order:
+						# Enforce correct merge order with a hard dep.
+						self.digraph.addnode(node, pnode,
+							priority=DepPriority(buildtime=True))
+						# Count references to this blocker so that it can be
+						# invalidated after nodes referencing it have been
+						# merged.
+						self.blocker_digraph.addnode(node, blocker)
+				if not unresolved_blocks and not depends_on_order:
+					self.blocker_parents[blocker].remove(parent)
+				if unresolved_blocks:
+					self._unresolved_blocker_parents.setdefault(
+						blocker, set()).add(parent)
+			if not self.blocker_parents[blocker]:
+				del self.blocker_parents[blocker]
+		# Validate blockers that depend on merge order.
+		if not self.blocker_digraph.empty():
+			self.altlist()
+		if self._slot_collision_info:
+			# The user is only notified of a slot collision if there are no
+			# unresolvable blocks.
+			for x in self.altlist():
+				if x[0] == "blocks":
+					return True
+			self._show_slot_collision_notice(self._slot_collision_info[0])
+			if not self._accept_collisions():
+				return False
+		return True
+
+	def _accept_collisions(self):
+		acceptable = False
+		for x in ("--nodeps", "--pretend", "--fetchonly", "--fetch-all-uri"):
+			if x in self.myopts:
+				acceptable = True
+				break
+		return acceptable
+
+	def _merge_order_bias(self, mygraph):
+		"""Order nodes from highest to lowest overall reference count for
+		optimal leaf node selection."""
+		node_info = {}
+		for node in mygraph.order:
+			node_info[node] = len(mygraph.parent_nodes(node))
+		def cmp_merge_preference(node1, node2):
+			return node_info[node2] - node_info[node1]
+		mygraph.order.sort(cmp_merge_preference)
+
+	def altlist(self, reversed=False):
+		if reversed in self._altlist_cache:
+			return self._altlist_cache[reversed][:]
+		if reversed:
+			retlist = self.altlist()
+			retlist.reverse()
+			self._altlist_cache[reversed] = retlist[:]
+			return retlist
+		mygraph=self.digraph.copy()
+		self._merge_order_bias(mygraph)
+		myblockers = self.blocker_digraph.copy()
+		retlist=[]
+		circular_blocks = False
+		blocker_deps = None
+		asap_nodes = []
+		if reversed:
+			get_nodes = mygraph.root_nodes
+		else:
+			get_nodes = mygraph.leaf_nodes
+			for cpv, node in self.pkg_node_map["/"].iteritems():
+				if "portage" == portage.catsplit(portage.dep_getkey(cpv))[-1]:
+					asap_nodes.append(node)
+					break
+		ignore_priority_range = [None]
+		ignore_priority_range.extend(
+			xrange(DepPriority.MIN, DepPriority.MEDIUM + 1))
+		tree_mode = "--tree" in self.myopts
+		while not mygraph.empty():
+			ignore_priority = None
+			nodes = None
+			if asap_nodes:
+				"""ASAP nodes are merged before their soft deps."""
+				for node in asap_nodes:
+					if not mygraph.contains(node):
+						asap_nodes.remove(node)
+						continue
+					if not mygraph.child_nodes(node,
+						ignore_priority=DepPriority.SOFT):
+						nodes = [node]
+						asap_nodes.remove(node)
+						break
+			if not nodes:
+				for ignore_priority in ignore_priority_range:
+					nodes = get_nodes(ignore_priority=ignore_priority)
+					if nodes:
+						break
+			selected_nodes = None
+			if nodes:
+				if ignore_priority <= DepPriority.SOFT:
+					if ignore_priority is None and not tree_mode:
+						# Greedily pop all of these nodes since no relationship
+						# has been ignored.  This optimization destroys --tree
+						# output, so it's disabled in reversed mode.
+						selected_nodes = nodes
+					else:
+						# For optimal merge order:
+						#  * Only pop one node.
+						#  * Removing a root node (node without a parent)
+						#    will not produce a leaf node, so avoid it.
+						for node in nodes:
+							if mygraph.parent_nodes(node):
+								# found a non-root node
+								selected_nodes = [node]
+								break
+						if not selected_nodes:
+							# settle for a root node
+							selected_nodes = [nodes[0]]
+				else:
+					"""Recursively gather a group of nodes that RDEPEND on
+					eachother.  This ensures that they are merged as a group
+					and get their RDEPENDs satisfied as soon as possible."""
+					def gather_deps(mergeable_nodes, selected_nodes, node):
+						if node in selected_nodes:
+							return True
+						if node not in mergeable_nodes:
+							return False
+						selected_nodes.add(node)
+						for child in mygraph.child_nodes(node,
+							ignore_priority=DepPriority.SOFT):
+							if not gather_deps(
+								mergeable_nodes, selected_nodes, child):
+								return False
+						return True
+					mergeable_nodes = set(nodes)
+					for node in nodes:
+						selected_nodes = set()
+						if gather_deps(
+							mergeable_nodes, selected_nodes, node):
+							break
+						else:
+							selected_nodes = None
+
+			if not selected_nodes:
+				if not myblockers.is_empty():
+					"""A blocker couldn't be circumnavigated while keeping all
+					dependencies satisfied.  The user will have to resolve this
+					manually.  This is a panic condition and thus the order
+					doesn't really matter, so just pop a random node in order
+					to avoid a circular dependency panic if possible."""
+					if not circular_blocks:
+						circular_blocks = True
+						blocker_deps = myblockers.leaf_nodes()
+					if blocker_deps:
+						selected_nodes = [blocker_deps.pop()]
+
+			if not selected_nodes:
+				# No leaf nodes are available, so we have a circular
+				# dependency panic situation.  Reduce the noise level to a
+				# minimum via repeated elimination of root nodes since they
+				# have no parents and thus can not be part of a cycle.
+				while True:
+					root_nodes = mygraph.root_nodes(
+						ignore_priority=DepPriority.SOFT)
+					if not root_nodes:
+						break
+					for node in root_nodes:
+						mygraph.remove(node)
+				# Display the USE flags that are enabled on nodes that are part
+				# of dependency cycles in case that helps the user decide to
+				# disable some of them.
+				display_order = []
+				tempgraph = mygraph.copy()
+				while not tempgraph.empty():
+					nodes = tempgraph.leaf_nodes()
+					if not nodes:
+						node = tempgraph.order[0]
+					else:
+						node = nodes[0]
+					display_order.append(list(node))
+					tempgraph.remove(node)
+				display_order.reverse()
+				self.myopts.pop("--quiet", None)
+				self.myopts.pop("--verbose", None)
+				self.myopts["--tree"] = True
+				self.display(display_order)
+				print "!!! Error: circular dependencies:"
+				print
+				mygraph.debug_print()
+				print
+				print "!!! Note that circular dependencies can often be avoided by temporarily"
+				print "!!! disabling USE flags that trigger optional dependencies."
+				sys.exit(1)
+
+			for node in selected_nodes:
+				retlist.append(list(node))
+				mygraph.remove(node)
+				if not reversed and not circular_blocks and myblockers.contains(node):
+					"""This node may have invalidated one or more blockers."""
+					myblockers.remove(node)
+					for blocker in myblockers.root_nodes():
+						if not myblockers.child_nodes(blocker):
+							myblockers.remove(blocker)
+							unresolved = \
+								self._unresolved_blocker_parents.get(blocker)
+							if unresolved:
+								self.blocker_parents[blocker] = unresolved
+							else:
+								del self.blocker_parents[blocker]
+
+		if not reversed:
+			"""Blocker validation does not work with reverse mode,
+			so self.altlist() should first be called with reverse disabled
+			so that blockers are properly validated."""
+			self.blocker_digraph = myblockers
+
+		""" Add any unresolved blocks so that they can be displayed."""
+		for blocker in self.blocker_parents:
+			retlist.append(list(blocker))
+		self._altlist_cache[reversed] = retlist[:]
+		return retlist
+
+	def xcreate(self,mode="system"):
+		vardb = self.trees[self.target_root]["vartree"].dbapi
+		portdb = self.trees[self.target_root]["porttree"].dbapi
+		bindb = self.trees[self.target_root]["bintree"].dbapi
+		def visible(mylist):
+			matches = portdb.gvisible(portdb.visible(mylist))
+			return [x for x in mylist \
+				if x in matches or not portdb.cpv_exists(x)]
+		world_problems = False
+		if mode=="system":
+			mylist = getlist(self.settings, "system")
+		else:
+			#world mode
+			worldlist = getlist(self.settings, "world")
+			sysdict = genericdict(getlist(self.settings, "system"))
+			worlddict=genericdict(worldlist)
+
+			for x in worlddict.keys():
+				if not portage.isvalidatom(x):
+					world_problems = True
+				elif not self.trees[self.target_root]["vartree"].dbapi.match(x):
+					world_problems = True
+				else:
+					sysdict[x]=worlddict[x]
+
+			mylist = sysdict.keys()
+
+		newlist = []
+		for atom in mylist:
+			mykey = portage.dep_getkey(atom)
+			if True:
+				newlist.append(atom)
+				"""Make sure all installed slots are updated when possible.
+				Do this with --emptytree also, to ensure that all slots are
+				remerged."""
+				myslots = set()
+				for cpv in vardb.match(mykey):
+					myslots.add(vardb.aux_get(cpv, ["SLOT"])[0])
+				if myslots:
+					best_pkgs = []
+					if "--usepkg" in self.myopts:
+						mymatches = bindb.match(atom)
+						if "--usepkgonly" not in self.myopts:
+							mymatches = visible(mymatches)
+						best_pkg = portage.best(mymatches)
+						if best_pkg:
+							best_slot = bindb.aux_get(best_pkg, ["SLOT"])[0]
+							best_pkgs.append(("binary", best_pkg, best_slot))
+					if "--usepkgonly" not in self.myopts:
+						best_pkg = portage.best(portdb.match(atom))
+						if best_pkg:
+							best_slot = portdb.aux_get(best_pkg, ["SLOT"])[0]
+							best_pkgs.append(("ebuild", best_pkg, best_slot))
+					if best_pkgs:
+						best_pkg = portage.best([x[1] for x in best_pkgs])
+						best_pkgs = [x for x in best_pkgs if x[1] == best_pkg]
+						best_slot = best_pkgs[0][2]
+						myslots.add(best_slot)
+				if len(myslots) > 1:
+					for myslot in myslots:
+						myslot_atom = "%s:%s" % (mykey, myslot)
+						available = False
+						if "--usepkgonly" not in self.myopts and \
+							self.trees[self.target_root][
+							"porttree"].dbapi.match(myslot_atom):
+							available = True
+						elif "--usepkg" in self.myopts:
+							mymatches = bindb.match(myslot_atom)
+							if "--usepkgonly" not in self.myopts:
+								mymatches = visible(mymatches)
+							if mymatches:
+								available = True
+						if available:
+							newlist.append(myslot_atom)
+		mylist = newlist
+		
+		missing_atoms = []
+		for mydep in mylist:
+			try:
+				if not self.select_dep(
+					self.target_root, mydep, raise_on_missing=True, arg=mydep):
+					print >> sys.stderr, "\n\n!!! Problem resolving dependencies for", mydep
+					return 0
+			except ValueError:
+				missing_atoms.append(mydep)
+
+		if not self.validate_blockers():
+			return False
+
+		if world_problems:
+			print >> sys.stderr, "\n!!! Problems have been detected with your world file"
+			print >> sys.stderr, "!!! Please run "+green("emaint --check world")+"\n"
+
+		if missing_atoms:
+			print >> sys.stderr, "\n" + colorize("BAD", "!!!") + \
+				" Ebuilds for the following packages are either all"
+			print >> sys.stderr, colorize("BAD", "!!!") + " masked or don't exist:"
+			print >> sys.stderr, " ".join(missing_atoms) + "\n"
+
+		return 1
+
+	def display(self,mylist,verbosity=None):
+		if verbosity is None:
+			verbosity = ("--quiet" in self.myopts and 1 or \
+				"--verbose" in self.myopts and 3 or 2)
+		changelogs=[]
+		p=[]
+		blockers = []
+
+		counters = PackageCounters()
+
+		if verbosity == 1 and "--verbose" not in self.myopts:
+			def create_use_string(*args):
+				return ""
+		else:
+			def create_use_string(name, cur_iuse, iuse_forced, cur_use,
+				old_iuse, old_use,
+				is_new, all_flags=(verbosity == 3 or "--quiet" in self.myopts),
+				alphabetical=("--alphabetical" in self.myopts)):
+				enabled = []
+				if alphabetical:
+					disabled = enabled
+					removed = enabled
+				else:
+					disabled = []
+					removed = []
+				cur_iuse = set(cur_iuse)
+				enabled_flags = cur_iuse.intersection(cur_use)
+				removed_iuse = set(old_iuse).difference(cur_iuse)
+				any_iuse = cur_iuse.union(old_iuse)
+				any_iuse = list(any_iuse)
+				any_iuse.sort()
+				for flag in any_iuse:
+					flag_str = None
+					isEnabled = False
+					if flag in enabled_flags:
+						isEnabled = True
+						if is_new or flag in old_use and all_flags:
+							flag_str = red(flag)
+						elif flag not in old_iuse:
+							flag_str = yellow(flag) + "%*"
+						elif flag not in old_use:
+							flag_str = green(flag) + "*"
+					elif flag in removed_iuse:
+						if all_flags:
+							flag_str = yellow("-" + flag) + "%"
+							if flag in old_use:
+								flag_str += "*"
+							flag_str = "(" + flag_str + ")"
+							removed.append(flag_str)
+						continue
+					else:
+						if is_new or flag in old_iuse and flag not in old_use and all_flags:
+							flag_str = blue("-" + flag)
+						elif flag not in old_iuse:
+							flag_str = yellow("-" + flag)
+							if flag not in iuse_forced:
+								flag_str += "%"
+						elif flag in old_use:
+							flag_str = green("-" + flag) + "*"
+					if flag_str:
+						if flag in iuse_forced:
+							flag_str = "(" + flag_str + ")"
+						if isEnabled:
+							enabled.append(flag_str)
+						else:
+							disabled.append(flag_str)
+
+				if alphabetical:
+					ret = " ".join(enabled)
+				else:
+					ret = " ".join(enabled + disabled + removed)
+				if ret:
+					ret = '%s="%s" ' % (name, ret)
+				return ret
+
+		if verbosity == 3:
+			# FIXME: account for the possibility of different overlays in
+			# /etc/make.conf vs. ${PORTAGE_CONFIGROOT}/etc/make.conf
+			overlays = self.settings["PORTDIR_OVERLAY"].split()
+			overlays_real = [os.path.realpath(t) \
+				for t in self.settings["PORTDIR_OVERLAY"].split()]
+
+		tree_nodes = []
+		display_list = []
+		mygraph = self._parent_child_digraph
+		i = 0
+		depth = 0
+		for x in mylist:
+			if "blocks" == x[0]:
+				display_list.append((x, 0, True))
+				continue
+			graph_key = tuple(x)
+			if "--tree" in self.myopts:
+				depth = len(tree_nodes)
+				while depth and graph_key not in \
+					mygraph.child_nodes(tree_nodes[depth-1]):
+						depth -= 1
+				if depth:
+					tree_nodes = tree_nodes[:depth]
+					tree_nodes.append(graph_key)
+					display_list.append((x, depth, True))
+				else:
+					traversed_nodes = set() # prevent endless circles
+					traversed_nodes.add(graph_key)
+					def add_parents(current_node, ordered):
+						parent_nodes = mygraph.parent_nodes(current_node)
+						if parent_nodes:
+							child_nodes = set(mygraph.child_nodes(current_node))
+							selected_parent = None
+							# First, try to avoid a direct cycle.
+							for node in parent_nodes:
+								if node not in traversed_nodes and \
+									node not in child_nodes:
+									selected_parent = node
+									break
+							if not selected_parent:
+								# A direct cycle is unavoidable.
+								for node in parent_nodes:
+									if node not in traversed_nodes:
+										selected_parent = node
+										break
+							if selected_parent:
+								traversed_nodes.add(selected_parent)
+								add_parents(selected_parent, False)
+						display_list.append((list(current_node),
+							len(tree_nodes), ordered))
+						tree_nodes.append(current_node)
+					tree_nodes = []
+					add_parents(graph_key, True)
+			else:
+				display_list.append((x, depth, True))
+		mylist = display_list
+
+		last_merge_depth = 0
+		for i in xrange(len(mylist)-1,-1,-1):
+			graph_key, depth, ordered = mylist[i]
+			if not ordered and depth == 0 and i > 0 \
+				and graph_key == mylist[i-1][0] and \
+				mylist[i-1][1] == 0:
+				# An ordered node got a consecutive duplicate when the tree was
+				# being filled in.
+				del mylist[i]
+				continue
+			if "blocks" == graph_key[0]:
+				continue
+			if ordered and graph_key[-1] != "nomerge":
+				last_merge_depth = depth
+				continue
+			if depth >= last_merge_depth or \
+				i < len(mylist) - 1 and \
+				depth >= mylist[i+1][1]:
+					del mylist[i]
+
+		display_overlays=False
+		# files to fetch list - avoids counting a same file twice
+		# in size display (verbose mode)
+		myfetchlist=[]
+		for mylist_index in xrange(len(mylist)):
+			x, depth, ordered = mylist[mylist_index]
+			pkg_type = x[0]
+			myroot = x[1]
+			pkg_key = x[2]
+			portdb = self.trees[myroot]["porttree"].dbapi
+			bindb  = self.trees[myroot]["bintree"].dbapi
+			vardb = self.trees[myroot]["vartree"].dbapi
+			vartree = self.trees[myroot]["vartree"]
+			pkgsettings = self.pkgsettings[myroot]
+
+			fetch=" "
+
+			if x[0]=="blocks":
+				addl=""+red("B")+"  "+fetch+"  "
+				if ordered:
+					counters.blocks += 1
+				resolved = portage.key_expand(
+					pkg_key, mydb=vardb, settings=pkgsettings)
+				if "--columns" in self.myopts and "--quiet" in self.myopts:
+					addl = addl + " " + red(resolved)
+				else:
+					addl = "[blocks " + addl + "] " + red(resolved)
+				block_parents = self.blocker_parents[tuple(x)]
+				block_parents = set([pnode[2] for pnode in block_parents])
+				block_parents = ", ".join(block_parents)
+				if resolved!=x[2]:
+					addl += bad(" (\"%s\" is blocking %s)") % \
+						(pkg_key, block_parents)
+				else:
+					addl += bad(" (is blocking %s)") % block_parents
+				blockers.append(addl)
+			else:
+				mydbapi = self.trees[myroot][self.pkg_tree_map[pkg_type]].dbapi
+				binary_package = True
+				if "ebuild" == pkg_type:
+					if "merge" == x[3] or \
+						not vartree.dbapi.cpv_exists(pkg_key):
+						"""An ebuild "merge" node or a --onlydeps "nomerge"
+						node."""
+						binary_package = False
+						pkgsettings.setcpv(pkg_key, mydb=portdb)
+						if pkg_key not in self.useFlags[myroot]:
+							self.useFlags[myroot][pkg_key] = \
+								pkgsettings["USE"].split()
+					else:
+						# An ebuild "nomerge" node, so USE come from the vardb.
+						mydbapi = vartree.dbapi
+				if pkg_key not in self.useFlags[myroot]:
+					"""If this is a --resume then the USE flags need to be
+					fetched from the appropriate locations here."""
+					self.useFlags[myroot][pkg_key] = mydbapi.aux_get(
+						pkg_key, ["USE"])[0].split()
+
+				if "ebuild" == pkg_type and x[3] != "nomerge" and \
+					"fetch" in portdb.aux_get(
+					x[2], ["RESTRICT"])[0].split():
+					fetch = red("F")
+					if ordered:
+						counters.restrict_fetch += 1
+					if portdb.fetch_check(
+						pkg_key, self.useFlags[myroot][pkg_key]):
+						fetch = green("f")
+						if ordered:
+							counters.restrict_fetch_satisfied += 1
+
+				#we need to use "--emptrytree" testing here rather than "empty" param testing because "empty"
+				#param is used for -u, where you still *do* want to see when something is being upgraded.
+				myoldbest=""
+				if vardb.cpv_exists(pkg_key):
+					addl="  "+yellow("R")+fetch+"  "
+					if x[3] != "nomerge":
+						if ordered:
+							counters.reinst += 1
+				elif vardb.match(portage.dep_getkey(pkg_key)):
+					mynewslot = mydbapi.aux_get(pkg_key, ["SLOT"])[0]
+					myoldlist = self.trees[x[1]]["vartree"].dbapi.match(
+						portage.pkgsplit(x[2])[0])
+					myinslotlist = [inst_pkg for inst_pkg in myoldlist
+						if mynewslot == vardb.aux_get(inst_pkg, ["SLOT"])[0]]
+					if myinslotlist:
+						myoldbest=portage.best(myinslotlist)
+						addl="   "+fetch
+						if portage.pkgcmp(portage.pkgsplit(x[2]), portage.pkgsplit(myoldbest)) < 0:
+							# Downgrade in slot
+							addl+=turquoise("U")+blue("D")
+							if ordered:
+								counters.downgrades += 1
+						else:
+							# Update in slot
+							addl+=turquoise("U")+" "
+							if ordered:
+								counters.upgrades += 1
+					else:
+						# New slot, mark it new.
+						addl=" "+green("NS")+fetch+"  "
+						if ordered:
+							counters.newslot += 1
+
+					if "--changelog" in self.myopts:
+						slot_atom = "%s:%s" % (portage.dep_getkey(pkg_key),
+							mydbapi.aux_get(pkg_key, ["SLOT"])[0])
+						inst_matches = vardb.match(slot_atom)
+						if inst_matches:
+							changelogs.extend(self.calc_changelog(
+								portdb.findname(pkg_key),
+								inst_matches[0], pkg_key))
+				else:
+					addl=" "+green("N")+" "+fetch+"  "
+					if ordered:
+						counters.new += 1
+
+				verboseadd=""
+				
+				if pkg_key in self.useFlags[myroot]:
+					# USE flag display
+					cur_iuse = list(filter_iuse_defaults(
+						mydbapi.aux_get(pkg_key, ["IUSE"])[0].split()))
+
+					forced_flags = set()
+					if not binary_package:
+						forced_flags.update(pkgsettings.useforce)
+						forced_flags.update(pkgsettings.usemask)
+
+					cur_iuse = portage.unique_array(cur_iuse)
+					cur_iuse.sort()
+					cur_use = self.useFlags[myroot][pkg_key]
+					cur_use = [flag for flag in cur_use if flag in cur_iuse]
+
+					if myoldbest:
+						pkg = myoldbest
+					else:
+						pkg = x[2]
+					if self.trees[x[1]]["vartree"].dbapi.cpv_exists(pkg):
+						old_iuse, old_use = \
+							self.trees[x[1]]["vartree"].dbapi.aux_get(
+								pkg, ["IUSE", "USE"])
+						old_iuse = list(set(
+							filter_iuse_defaults(old_iuse.split())))
+						old_iuse.sort()
+						old_use = old_use.split()
+						is_new = False
+					else:
+						old_iuse = []
+						old_use = []
+						is_new = True
+
+					old_use = [flag for flag in old_use if flag in old_iuse]
+
+					use_expand = pkgsettings["USE_EXPAND"].lower().split()
+					use_expand.sort()
+					use_expand.reverse()
+					use_expand_hidden = \
+						pkgsettings["USE_EXPAND_HIDDEN"].lower().split()
+
+					def map_to_use_expand(myvals, forcedFlags=False):
+						ret = {}
+						forced = {}
+						for exp in use_expand:
+							ret[exp] = []
+							forced[exp] = set()
+							for val in myvals[:]:
+								if val.startswith(exp.lower()+"_"):
+									if val in forced_flags:
+										forced[exp].add(val[len(exp)+1:])
+									ret[exp].append(val[len(exp)+1:])
+									myvals.remove(val)
+						ret["USE"] = myvals
+						forced["USE"] = [val for val in myvals \
+							if val in forced_flags]
+						for exp in use_expand_hidden:
+							if exp in ret:
+								del ret[exp]
+						if forcedFlags:
+							return ret, forced
+						return ret
+
+					cur_iuse_map, iuse_forced = \
+						map_to_use_expand(cur_iuse, forcedFlags=True)
+					cur_use_map = map_to_use_expand(cur_use)
+					old_iuse_map = map_to_use_expand(old_iuse)
+					old_use_map = map_to_use_expand(old_use)
+
+					use_expand.sort()
+					use_expand.insert(0, "USE")
+					
+					for key in use_expand:
+						if key in use_expand_hidden:
+							continue
+						verboseadd += create_use_string(key.upper(),
+							cur_iuse_map[key], iuse_forced[key],
+							cur_use_map[key], old_iuse_map[key],
+							old_use_map[key], is_new)
+
+				if verbosity == 3:
+					# size verbose
+					mysize=0
+					if x[0] == "ebuild" and ordered and x[-1] != "nomerge":
+						try:
+							myfilesdict = portdb.getfetchsizes(pkg_key,
+								useflags=self.useFlags[myroot][pkg_key],
+								debug=self.edebug)
+						except portage_exception.InvalidDependString, e:
+							src_uri = portdb.aux_get(pkg_key, ["SRC_URI"])[0]
+							show_invalid_depstring_notice(x, src_uri, str(e))
+							del e
+							sys.exit(1)
+						if myfilesdict is None:
+							myfilesdict="[empty/missing/bad digest]"
+						else:
+							for myfetchfile in myfilesdict.keys():
+								if myfetchfile not in myfetchlist:
+									mysize+=myfilesdict[myfetchfile]
+									myfetchlist.append(myfetchfile)
+							counters.totalsize += mysize
+						verboseadd+=format_size(mysize)+" "
+
+					# overlay verbose
+					# XXX: Invalid binaries have caused tracebacks here. 'if file_name'
+					# x = ['binary', '/', 'sys-apps/pcmcia-cs-3.2.7.2.6', 'merge']
+					file_name = portdb.findname(pkg_key)
+					if file_name: # It might not exist in the tree
+						dir_name=os.path.abspath(os.path.dirname(file_name)+"/../..")
+						if (overlays_real.count(dir_name)>0):
+							verboseadd+=teal("["+str(overlays_real.index(
+								os.path.normpath(dir_name))+1)+"]")+" "
+							display_overlays=True
+					else:
+						verboseadd += "[No ebuild?]"
+
+				xs=portage.pkgsplit(x[2])
+				if xs[2]=="r0":
+					xs[2]=""
+				else:
+					xs[2]="-"+xs[2]
+
+				mywidth = 130
+				if "COLUMNWIDTH" in self.settings:
+					try:
+						mywidth = int(self.settings["COLUMNWIDTH"])
+					except ValueError, e:
+						portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
+						portage.writemsg(
+							"!!! Unable to parse COLUMNWIDTH='%s'\n" % \
+							self.settings["COLUMNWIDTH"], noiselevel=-1)
+						del e
+				oldlp=mywidth-30
+				newlp=oldlp-30
+
+				indent = " " * depth
+
+				if myoldbest:
+					myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
+					if myoldbest[-3:]=="-r0":
+						myoldbest=myoldbest[:-3]
+					myoldbest=blue("["+myoldbest+"]")
+
+				if x[1]!="/":
+					if myoldbest:
+						myoldbest +=" "
+					if "--columns" in self.myopts:
+						if "--quiet" in self.myopts:
+							myprint=addl+" "+indent+darkgreen(xs[0])
+							myprint=myprint+darkblue(" "+xs[1]+xs[2])+" "
+							myprint=myprint+myoldbest
+							myprint=myprint+darkgreen("to "+x[1])
+						else:
+							myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
+							if (newlp-nc_len(myprint)) > 0:
+								myprint=myprint+(" "*(newlp-nc_len(myprint)))
+							myprint=myprint+"["+darkblue(xs[1]+xs[2])+"] "
+							if (oldlp-nc_len(myprint)) > 0:
+								myprint=myprint+" "*(oldlp-nc_len(myprint))
+							myprint=myprint+myoldbest
+							myprint=myprint+darkgreen("to "+x[1])+" "+verboseadd
+					else:
+						if x[-1] == "nomerge" or not ordered:
+							myprint = darkblue("[nomerge      ] ")
+						else:
+							myprint = "[" + pkg_type + " " + addl + "] "
+						myprint += indent + darkgreen(pkg_key) + " " + \
+							myoldbest + darkgreen("to " + myroot) + " " + \
+							verboseadd
+				else:
+					if "--columns" in self.myopts:
+						if "--quiet" in self.myopts:
+							myprint=addl+" "+indent+darkgreen(xs[0])
+							myprint=myprint+" "+green(xs[1]+xs[2])+" "
+							myprint=myprint+myoldbest
+						else:
+							myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
+							if (newlp-nc_len(myprint)) > 0:
+								myprint=myprint+(" "*(newlp-nc_len(myprint)))
+							myprint=myprint+green(" ["+xs[1]+xs[2]+"] ")
+							if (oldlp-nc_len(myprint)) > 0:
+								myprint=myprint+(" "*(oldlp-nc_len(myprint)))
+							myprint=myprint+myoldbest+"  "+verboseadd
+					else:
+						if x[-1] == "nomerge" or not ordered:
+							myprint=darkblue("[nomerge      ] "+indent+x[2]+" "+myoldbest+" ")+verboseadd
+						else:
+							myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(x[2])+" "+myoldbest+" "+verboseadd
+				p.append(myprint)
+
+			mysplit = portage.pkgsplit(x[2])
+			if "--tree" not in self.myopts and mysplit and \
+				len(mysplit) == 3 and mysplit[0] == "sys-apps/portage" and \
+				x[1] == "/":
+
+				if mysplit[2] == "r0":
+					myversion = mysplit[1]
+				else:
+					myversion = "%s-%s" % (mysplit[1], mysplit[2])
+
+				if myversion != portage.VERSION and "--quiet" not in self.myopts:
+					if mylist_index < len(mylist) - 1 and \
+						"livecvsportage" not in self.settings.features:
+						p.append(colorize("WARN", "*** Portage will stop merging at this point and reload itself,"))
+						p.append(colorize("WARN", "    then resume the merge."))
+						print
+			del mysplit
+
+		for x in p:
+			print x
+		for x in blockers:
+			print x
+
+		if verbosity == 3:
+			print
+			print counters
+			if overlays and display_overlays:
+				print "Portage overlays:"
+				y=0
+				for x in overlays:
+					y=y+1
+					print " "+teal("["+str(y)+"]"),x
+
+		if "--changelog" in self.myopts:
+			print
+			for revision,text in changelogs:
+				print bold('*'+revision)
+				sys.stdout.write(text)
+
+		if self._pprovided_args:
+			msg = []
+			msg.append(bad("\nWARNING: "))
+			if len(self._pprovided_args) > 1:
+				msg.append("Requested packages will not be " + \
+					"merged because they are listed in\n")
+			else:
+				msg.append("A requested package will not be " + \
+					"merged because it is listed in\n")
+			msg.append("         package.provided:\n\n")
+			for arg in self._pprovided_args:
+				msg.append("             " + arg + "\n")
+			msg.append("\n")
+			sys.stderr.write("".join(msg))
+
+	def calc_changelog(self,ebuildpath,current,next):
+		current = '-'.join(portage.catpkgsplit(current)[1:])
+		if current.endswith('-r0'): current = current[:-3]
+		next = '-'.join(portage.catpkgsplit(next)[1:])
+		if next.endswith('-r0'): next = next[:-3]
+		changelogpath = os.path.join(os.path.split(ebuildpath)[0],'ChangeLog')
+		try:
+			changelog = open(changelogpath).read()
+		except SystemExit, e:
+			raise # Needed else can't exit
+		except:
+			return []
+		divisions = self.find_changelog_tags(changelog)
+		#print 'XX from',current,'to',next
+		#for div,text in divisions: print 'XX',div
+		# skip entries for all revisions above the one we are about to emerge
+		for i in range(len(divisions)):
+			if divisions[i][0]==next:
+				divisions = divisions[i:]
+				break
+		# find out how many entries we are going to display
+		for i in range(len(divisions)):
+			if divisions[i][0]==current:
+				divisions = divisions[:i]
+				break
+		else:
+		    # couldnt find the current revision in the list. display nothing
+			return []
+		return divisions
+
+	def find_changelog_tags(self,changelog):
+		divs = []
+		release = None
+		while 1:
+			match = re.search(r'^\*\ ?([-a-zA-Z0-9_.+]*)(?:\ .*)?\n',changelog,re.M)
+			if match is None:
+				if release is not None:
+					divs.append((release,changelog))
+				return divs
+			if release is not None:
+				divs.append((release,changelog[:match.start()]))
+			changelog = changelog[match.end():]
+			release = match.group(1)
+			if release.endswith('.ebuild'):
+				release = release[:-7]
+			if release.endswith('-r0'):
+				release = release[:-3]
+
+	def outdated(self):
+		return self.outdatedpackages
+
+class PackageCounters(object):
+
+	def __init__(self):
+		self.upgrades   = 0
+		self.downgrades = 0
+		self.new        = 0
+		self.newslot    = 0
+		self.reinst     = 0
+		self.blocks     = 0
+		self.totalsize  = 0
+		self.restrict_fetch           = 0
+		self.restrict_fetch_satisfied = 0
+
+	def __str__(self):
+		total_installs = self.upgrades + self.downgrades + self.newslot + self.new + self.reinst
+		myoutput = []
+		details = []
+		myoutput.append("Total: %s package" % total_installs)
+		if total_installs != 1:
+			myoutput.append("s")
+		if total_installs != 0:
+			myoutput.append(" (")
+		if self.upgrades > 0:
+			details.append("%s upgrade" % self.upgrades)
+			if self.upgrades > 1:
+				details[-1] += "s"
+		if self.downgrades > 0:
+			details.append("%s downgrade" % self.downgrades)
+			if self.downgrades > 1:
+				details[-1] += "s"
+		if self.new > 0:
+			details.append("%s new" % self.new)
+		if self.newslot > 0:
+			details.append("%s in new slot" % self.newslot)
+			if self.newslot > 1:
+				details[-1] += "s"
+		if self.reinst > 0:
+			details.append("%s reinstall" % self.reinst)
+			if self.reinst > 1:
+				details[-1] += "s"
+		if self.blocks > 0:
+			details.append("%s block" % self.blocks)
+			if self.blocks > 1:
+				details[-1] += "s"
+		myoutput.append(", ".join(details))
+		if total_installs != 0:
+			myoutput.append(")")
+		myoutput.append(", Size of downloads: %s" % format_size(self.totalsize))
+		if self.restrict_fetch:
+			myoutput.append("\nFetch Restriction: %s package" % \
+				self.restrict_fetch)
+			if self.restrict_fetch > 1:
+				myoutput.append("s")
+		if self.restrict_fetch_satisfied < self.restrict_fetch:
+			myoutput.append(bad(" (%s unsatisfied)") % \
+				(self.restrict_fetch - self.restrict_fetch_satisfied))
+		return "".join(myoutput)
+
+class MergeTask(object):
+
+	def __init__(self, settings, trees, myopts):
+		self.settings = settings
+		self.target_root = settings["ROOT"]
+		self.trees = trees
+		self.myopts = myopts
+		self.edebug = 0
+		if settings.get("PORTAGE_DEBUG", "") == "1":
+			self.edebug = 1
+		self.pkgsettings = {}
+		self.pkgsettings[self.target_root] = portage.config(clone=settings)
+		if self.target_root != "/":
+			self.pkgsettings["/"] = \
+				portage.config(clone=trees["/"]["vartree"].settings)
+
+	def merge(self, mylist, favorites, mtimedb):
+		failed_fetches = []
+		mymergelist=[]
+		ldpath_mtimes = mtimedb["ldpath"]
+		xterm_titles = "notitles" not in self.settings.features
+
+		#check for blocking dependencies
+		if "--fetchonly" not in self.myopts and \
+			"--fetch-all-uri" not in self.myopts and \
+			"--buildpkgonly" not in self.myopts:
+			for x in mylist:
+				if x[0]=="blocks":
+					print "\n!!! Error: the "+x[2]+" package conflicts with another package;"
+					print   "!!!        the two packages cannot be installed on the same system together."
+					print   "!!!        Please use 'emerge --pretend' to determine blockers."
+					if "--quiet" not in self.myopts:
+						show_blocker_docs_link()
+					return 1
+
+		if "--resume" in self.myopts:
+			# We're resuming.
+			print colorize("GOOD", "*** Resuming merge...")
+			emergelog(xterm_titles, " *** Resuming merge...")
+			mylist = mtimedb["resume"]["mergelist"][:]
+			if "--skipfirst" in self.myopts and mylist:
+				del mtimedb["resume"]["mergelist"][0]
+				del mylist[0]
+				mtimedb.commit()
+			validate_merge_list(self.trees, mylist)
+			mymergelist = mylist
+
+		# Verify all the manifests now so that the user is notified of failure
+		# as soon as possible.
+		if "--fetchonly" not in self.myopts and \
+			"--fetch-all-uri" not in self.myopts and \
+			"strict" in self.settings.features:
+			shown_verifying_msg = False
+			quiet_settings = {}
+			for myroot, pkgsettings in self.pkgsettings.iteritems():
+				quiet_config = portage.config(clone=pkgsettings)
+				quiet_config["PORTAGE_QUIET"] = "1"
+				quiet_config.backup_changes("PORTAGE_QUIET")
+				quiet_settings[myroot] = quiet_config
+				del quiet_config
+			for x in mylist:
+				if x[0] != "ebuild" or x[-1] == "nomerge":
+					continue
+				if not shown_verifying_msg:
+					shown_verifying_msg = True
+					print ">>> Verifying ebuild Manifests..."
+				mytype, myroot, mycpv, mystatus = x
+				portdb = self.trees[myroot]["porttree"].dbapi
+				quiet_config = quiet_settings[myroot]
+				quiet_config["O"] = os.path.dirname(portdb.findname(mycpv))
+				if not portage.digestcheck([], quiet_config, strict=True):
+					return 1
+				del x, mytype, myroot, mycpv, mystatus, quiet_config
+			del shown_verifying_msg, quiet_settings
+
+		#buildsyspkg: I need mysysdict also on resume (moved from the else block)
+		mysysdict = genericdict(getlist(self.settings, "system"))
+		if "--resume" not in self.myopts:
+			myfavs = portage.grabfile(
+				os.path.join(self.target_root, portage.WORLD_FILE))
+			myfavdict=genericdict(myfavs)
+			for x in range(len(mylist)):
+				if mylist[x][3]!="nomerge":
+					# Add to the mergelist
+					mymergelist.append(mylist[x])
+				else:
+					myfavkey=portage.cpv_getkey(mylist[x][2])
+					if "--onlydeps" in self.myopts:
+						continue
+					# Add to the world file. Since we won't be able to later.
+					if "--fetchonly" not in self.myopts and \
+						myfavkey in favorites:
+						#don't record if already in system profile or already recorded
+						if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
+							#we don't have a favorites entry for this package yet; add one
+							myfavdict[myfavkey]=myfavkey
+							print ">>> Recording",myfavkey,"in \"world\" favorites file..."
+			if not ("--fetchonly" in self.myopts or \
+				"--fetch-all-uri" in self.myopts or \
+				"--pretend" in self.myopts):
+				portage.write_atomic(
+					os.path.join(self.target_root, portage.WORLD_FILE),
+					"\n".join(myfavdict.values()))
+
+			mtimedb["resume"]["mergelist"]=mymergelist[:]
+			mtimedb.commit()
+
+		myfeat = self.settings.features[:]
+		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
+			"--resume"])
+		if "parallel-fetch" in myfeat and \
+			not ("--pretend" in self.myopts or \
+			"--fetch-all-uri" in self.myopts or \
+			"--fetchonly" in self.myopts):
+			if "distlocks" not in myfeat:
+				print red("!!!")
+				print red("!!!")+" parallel-fetching requires the distlocks feature enabled"
+				print red("!!!")+" you have it disabled, thus parallel-fetching is being disabled"
+				print red("!!!")
+			elif len(mymergelist) > 1:
+				print ">>> starting parallel fetching"
+				fetch_log = "/var/log/emerge-fetch.log"
+				logfile = open(fetch_log, "w")
+				fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
+				portage_util.apply_secpass_permissions(fetch_log,
+					uid=portage.portage_uid, gid=portage.portage_gid,
+					mode=0660)
+				fetch_env = os.environ.copy()
+				fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
+				fetch_env["PORTAGE_NICENESS"] = "0"
+				fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
+				resume_opts = self.myopts.copy()
+				# For automatic resume, we need to prevent
+				# any of bad_resume_opts from leaking in
+				# via EMERGE_DEFAULT_OPTS.
+				resume_opts["--ignore-default-opts"] = True
+				for myopt, myarg in resume_opts.iteritems():
+					if myopt not in bad_resume_opts:
+						if myarg is True:
+							fetch_args.append(myopt)
+						else:
+							fetch_args.append(myopt +"="+ myarg)
+				portage.portage_exec.spawn(fetch_args, env=fetch_env,
+					fd_pipes=fd_pipes, returnpid=True)
+				logfile.close() # belongs to the spawned process
+				del fetch_log, logfile, fd_pipes, fetch_env, fetch_args, \
+					resume_opts
+
+		mergecount=0
+		for x in mymergelist:
+			mergecount+=1
+			myroot=x[1]
+			pkg_key = x[2]
+			pkgindex=2
+			portdb = self.trees[myroot]["porttree"].dbapi
+			bindb  = self.trees[myroot]["bintree"].dbapi
+			vartree = self.trees[myroot]["vartree"]
+			pkgsettings = self.pkgsettings[myroot]
+			if x[0]=="blocks":
+				pkgindex=3
+			y = portdb.findname(pkg_key)
+			if "--pretend" not in self.myopts:
+				print "\n>>> Emerging (" + \
+					colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
+					colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
+					colorize("GOOD", x[pkgindex]) + " to " + x[1]
+				emergelog(xterm_titles, " >>> emerge ("+\
+					str(mergecount)+" of "+str(len(mymergelist))+\
+					") "+x[pkgindex]+" to "+x[1])
+
+			pkgsettings["EMERGE_FROM"] = x[0]
+			pkgsettings.backup_changes("EMERGE_FROM")
+			pkgsettings.reset()
+
+			#buildsyspkg: Check if we need to _force_ binary package creation
+			issyspkg = ("buildsyspkg" in myfeat) \
+					and x[0] != "blocks" \
+					and mysysdict.has_key(portage.cpv_getkey(x[2])) \
+					and "--buildpkg" not in self.myopts
+			if x[0] in ["ebuild","blocks"]:
+				if x[0] == "blocks" and "--fetchonly" not in self.myopts:
+					raise Exception, "Merging a blocker"
+				elif "--fetchonly" in self.myopts or \
+					"--fetch-all-uri" in self.myopts:
+					if "--fetch-all-uri" in self.myopts:
+						retval = portage.doebuild(y, "fetch", myroot,
+							pkgsettings, self.edebug,
+							"--pretend" in self.myopts, fetchonly=1,
+							fetchall=1, mydbapi=portdb, tree="porttree")
+					else:
+						retval = portage.doebuild(y, "fetch", myroot,
+							pkgsettings, self.edebug,
+							"--pretend" in self.myopts, fetchonly=1,
+							mydbapi=portdb, tree="porttree")
+					if (retval is None) or retval:
+						print
+						print "!!! Fetch for",y,"failed, continuing..."
+						print
+						failed_fetches.append(pkg_key)
+					continue
+
+				portage.doebuild_environment(y, "setup", myroot,
+					pkgsettings, self.edebug, 1, portdb)
+				catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
+				portage_util.ensure_dirs(os.path.dirname(catdir),
+					uid=portage.portage_uid, gid=portage.portage_gid,
+					mode=070, mask=0)
+				builddir_lock = None
+				catdir_lock = None
+				try:
+					catdir_lock = portage_locks.lockdir(catdir)
+					portage_util.ensure_dirs(catdir,
+						uid=portage.portage_uid, gid=portage.portage_gid,
+						mode=070, mask=0)
+					builddir_lock = portage_locks.lockdir(
+						pkgsettings["PORTAGE_BUILDDIR"])
+					try:
+						portage_locks.unlockdir(catdir_lock)
+					finally:
+						catdir_lock = None
+					msg = " === (%s of %s) Cleaning (%s::%s)" % \
+						(mergecount, len(mymergelist), pkg_key, y)
+					short_msg = "emerge: (%s of %s) %s Clean" % \
+						(mergecount, len(mymergelist), pkg_key)
+					emergelog(xterm_titles, msg, short_msg=short_msg)
+					retval = portage.doebuild(y, "clean", myroot,
+						pkgsettings, self.edebug, cleanup=1,
+						mydbapi=portdb, tree="porttree")
+					if retval != os.EX_OK:
+						return retval
+					if "--buildpkg" in self.myopts or issyspkg:
+						if issyspkg:
+							print ">>> This is a system package, " + \
+								"let's pack a rescue tarball."
+						msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
+							(mergecount, len(mymergelist), pkg_key, y)
+						short_msg = "emerge: (%s of %s) %s Compile" % \
+							(mergecount, len(mymergelist), pkg_key)
+						emergelog(xterm_titles, msg, short_msg=short_msg)
+						self.trees[myroot]["bintree"].prevent_collision(pkg_key)
+						retval = portage.doebuild(y, "package", myroot,
+							pkgsettings, self.edebug, mydbapi=portdb,
+							tree="porttree")
+						if retval != os.EX_OK:
+							return retval
+						bintree = self.trees[myroot]["bintree"]
+						if bintree.populated:
+							bintree.inject(pkg_key)
+						if "--buildpkgonly" not in self.myopts:
+							msg = " === (%s of %s) Merging (%s::%s)" % \
+								(mergecount, len(mymergelist), pkg_key, y)
+							short_msg = "emerge: (%s of %s) %s Merge" % \
+								(mergecount, len(mymergelist), pkg_key)
+							emergelog(xterm_titles, msg, short_msg=short_msg)
+							retval = portage.merge(pkgsettings["CATEGORY"],
+								pkgsettings["PF"], pkgsettings["D"],
+								os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
+								"build-info"), myroot, pkgsettings,
+								myebuild=pkgsettings["EBUILD"],
+								mytree="porttree", mydbapi=portdb,
+								vartree=vartree, prev_mtimes=ldpath_mtimes)
+							if retval != os.EX_OK:
+								return retval
+						elif "noclean" not in pkgsettings.features:
+							portage.doebuild(y, "clean", myroot,
+								pkgsettings, self.edebug, mydbapi=portdb,
+								tree="porttree")
+					else:
+						msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
+							(mergecount, len(mymergelist), pkg_key, y)
+						short_msg = "emerge: (%s of %s) %s Compile" % \
+							(mergecount, len(mymergelist), pkg_key)
+						emergelog(xterm_titles, msg, short_msg=short_msg)
+						retval = portage.doebuild(y, "merge", myroot,
+							pkgsettings, self.edebug, vartree=vartree,
+							mydbapi=portdb, tree="porttree",
+							prev_mtimes=ldpath_mtimes)
+						if retval != os.EX_OK:
+							return retval
+				finally:
+					if builddir_lock:
+						portage_locks.unlockdir(builddir_lock)
+					try:
+						if not catdir_lock:
+							# Lock catdir for removal if empty.
+							catdir_lock = portage_locks.lockdir(catdir)
+					finally:
+						if catdir_lock:
+							try:
+								os.rmdir(catdir)
+							except OSError, e:
+								if e.errno not in (errno.ENOENT,
+									errno.ENOTEMPTY, errno.EEXIST):
+									raise
+								del e
+							portage_locks.unlockdir(catdir_lock)
+
+			elif x[0]=="binary":
+				#merge the tbz2
+				mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
+				if "--getbinpkg" in self.myopts:
+					tbz2_lock = None
+					try:
+						if "distlocks" in pkgsettings.features and \
+							os.access(pkgsettings["PKGDIR"], os.W_OK):
+							portage_util.ensure_dirs(os.path.dirname(mytbz2))
+							tbz2_lock = portage_locks.lockfile(mytbz2,
+								wantnewlockfile=1)
+						if self.trees[myroot]["bintree"].isremote(pkg_key):
+							msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
+								(mergecount, len(mymergelist), pkg_key, mytbz2)
+							short_msg = "emerge: (%s of %s) %s Fetch" % \
+								(mergecount, len(mymergelist), pkg_key)
+							emergelog(xterm_titles, msg, short_msg=short_msg)
+							if not self.trees[myroot]["bintree"].gettbz2(
+								pkg_key):
+								return 1
+					finally:
+						if tbz2_lock:
+							portage_locks.unlockfile(tbz2_lock)
+
+				if "--fetchonly" in self.myopts or \
+					"--fetch-all-uri" in self.myopts:
+					continue
+
+				short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
+				emergelog(xterm_titles, " === ("+str(mergecount)+\
+					" of "+str(len(mymergelist))+") Merging Binary ("+\
+					x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
+				retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
+					mydbapi=bindb,
+					vartree=self.trees[myroot]["vartree"],
+					prev_mtimes=ldpath_mtimes)
+				if retval != os.EX_OK:
+					return retval
+				#need to check for errors
+			if "--buildpkgonly" not in self.myopts:
+				self.trees[x[1]]["vartree"].inject(x[2])
+				myfavkey=portage.cpv_getkey(x[2])
+				if "--fetchonly" not in self.myopts and \
+					"--fetch-all-uri" not in self.myopts and \
+					myfavkey in favorites:
+					myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
+					myfavdict=genericdict(myfavs)
+					#don't record if already in system profile or already recorded
+					if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
+						#we don't have a favorites entry for this package yet; add one
+						myfavdict[myfavkey]=myfavkey
+						print ">>> Recording",myfavkey,"in \"world\" favorites file..."
+						emergelog(xterm_titles, " === ("+\
+							str(mergecount)+" of "+\
+							str(len(mymergelist))+\
+							") Updating world file ("+x[pkgindex]+")")
+						portage.write_atomic(
+						os.path.join(myroot, portage.WORLD_FILE),
+						"\n".join(myfavdict.values()))
+
+				if "--pretend" not in self.myopts and \
+					"--fetchonly" not in self.myopts and \
+					"--fetch-all-uri" not in self.myopts:
+					# Clean the old package that we have merged over top of it.
+					if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
+						xsplit=portage.pkgsplit(x[2])
+						emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
+						retval = unmerge(pkgsettings, self.myopts, vartree,
+							"clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
+						if not retval:
+							emergelog(xterm_titles,
+								" --- AUTOCLEAN: Nothing unmerged.")
+					else:
+						portage.writemsg_stdout(colorize("WARN", "WARNING:")
+							+ " AUTOCLEAN is disabled.  This can cause serious"
+							+ " problems due to overlapping packages.\n")
+
+					# Figure out if we need a restart.
+					mysplit=portage.pkgsplit(x[2])
+					if mysplit[0] == "sys-apps/portage" and x[1] == "/":
+						myver=mysplit[1]+"-"+mysplit[2]
+						if myver[-3:]=='-r0':
+							myver=myver[:-3]
+						if (myver != portage.VERSION) and \
+						   "livecvsportage" not in self.settings.features:
+							if len(mymergelist) > mergecount:
+								emergelog(xterm_titles,
+									" ::: completed emerge ("+ \
+									str(mergecount)+" of "+ \
+									str(len(mymergelist))+") "+ \
+									x[2]+" to "+x[1])
+								emergelog(xterm_titles, " *** RESTARTING " + \
+									"emerge via exec() after change of " + \
+									"portage version.")
+								del mtimedb["resume"]["mergelist"][0]
+								mtimedb.commit()
+								portage.run_exitfuncs()
+								mynewargv=[sys.argv[0],"--resume"]
+								resume_opts = self.myopts.copy()
+								# For automatic resume, we need to prevent
+								# any of bad_resume_opts from leaking in
+								# via EMERGE_DEFAULT_OPTS.
+								resume_opts["--ignore-default-opts"] = True
+								for myopt, myarg in resume_opts.iteritems():
+									if myopt not in bad_resume_opts:
+										if myarg is True:
+											mynewargv.append(myopt)
+										else:
+											mynewargv.append(myopt +"="+ myarg)
+								# priority only needs to be adjusted on the first run
+								os.environ["PORTAGE_NICENESS"] = "0"
+								os.execv(mynewargv[0], mynewargv)
+
+			if "--pretend" not in self.myopts and \
+				"--fetchonly" not in self.myopts and \
+				"--fetch-all-uri" not in self.myopts:
+				if "noclean" not in self.settings.features:
+					short_msg = "emerge: (%s of %s) %s Clean Post" % \
+						(mergecount, len(mymergelist), x[pkgindex])
+					emergelog(xterm_titles, (" === (%s of %s) " + \
+						"Post-Build Cleaning (%s::%s)") % \
+						(mergecount, len(mymergelist), x[pkgindex], y),
+						short_msg=short_msg)
+				emergelog(xterm_titles, " ::: completed emerge ("+\
+					str(mergecount)+" of "+str(len(mymergelist))+") "+\
+					x[2]+" to "+x[1])
+
+			# Unsafe for parallel merges
+			del mtimedb["resume"]["mergelist"][0]
+			# Commit after each merge so that --resume may still work in
+			# in the event that portage is not allowed to exit normally
+			# due to power failure, SIGKILL, etc...
+			mtimedb.commit()
+
+		if "--pretend" not in self.myopts:
+			emergelog(xterm_titles, " *** Finished. Cleaning up...")
+
+		# We're out of the loop... We're done. Delete the resume data.
+		if mtimedb.has_key("resume"):
+			del mtimedb["resume"]
+		mtimedb.commit()
+
+		#by doing an exit this way, --fetchonly can continue to try to
+		#fetch everything even if a particular download fails.
+		if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
+			if failed_fetches:
+				sys.stderr.write("\n\n!!! Some fetch errors were " + \
+					"encountered.  Please see above for details.\n\n")
+				for cpv in failed_fetches:
+					sys.stderr.write("   ")
+					sys.stderr.write(cpv)
+					sys.stderr.write("\n")
+				sys.stderr.write("\n")
+				sys.exit(1)
+			else:
+				sys.exit(0)
+		return os.EX_OK
+
+def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
+	ldpath_mtimes, autoclean=0):
+	candidate_catpkgs=[]
+	global_unmerge=0
+	xterm_titles = "notitles" not in settings.features
+
+	vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
+	try:
+		# At least the parent needs to exist for the lock file.
+		portage_util.ensure_dirs(vdb_path)
+	except portage_exception.PortageException:
+		pass
+	vdb_lock = None
+	try:
+		if os.access(vdb_path, os.W_OK):
+			vdb_lock = portage_locks.lockdir(vdb_path)
+		realsyslist = getlist(settings, "system")
+		syslist = []
+		for x in realsyslist:
+			mycp = portage.dep_getkey(x)
+			if mycp in settings.getvirtuals():
+				providers = []
+				for provider in settings.getvirtuals()[mycp]:
+					if vartree.dbapi.match(provider):
+						providers.append(provider)
+				if len(providers) == 1:
+					syslist.extend(providers)
+			else:
+				syslist.append(mycp)
+	
+		mysettings = portage.config(clone=settings)
+	
+		if not unmerge_files or "world" in unmerge_files or \
+			"system" in unmerge_files:
+			if "unmerge"==unmerge_action:
+				print
+				print bold("emerge unmerge") + " can only be used with " + \
+					"specific package names, not with "+bold("world")+" or"
+				print bold("system")+" targets."
+				print
+				return 0
+			else:
+				global_unmerge = 1
+	
+		localtree = vartree
+		# process all arguments and add all
+		# valid db entries to candidate_catpkgs
+		if global_unmerge:
+			if not unmerge_files or "world" in unmerge_files:
+				candidate_catpkgs.extend(vartree.dbapi.cp_all())
+			elif "system" in unmerge_files:
+				candidate_catpkgs.extend(getlist(settings, "system"))
+		else:
+			#we've got command-line arguments
+			if not unmerge_files:
+				print "\nNo packages to unmerge have been provided.\n"
+				return 0
+			for x in unmerge_files:
+				arg_parts = x.split('/')
+				if x[0] not in [".","/"] and \
+					arg_parts[-1][-7:] != ".ebuild":
+					#possible cat/pkg or dep; treat as such
+					candidate_catpkgs.append(x)
+				elif unmerge_action in ["prune","clean"]:
+					print "\n!!! Prune and clean do not accept individual" + \
+						" ebuilds as arguments;\n    skipping.\n"
+					continue
+				else:
+					# it appears that the user is specifying an installed
+					# ebuild and we're in "unmerge" mode, so it's ok.
+					if not os.path.exists(x):
+						print "\n!!! The path '"+x+"' doesn't exist.\n"
+						return 0
+	
+					absx   = os.path.abspath(x)
+					sp_absx = absx.split("/")
+					if sp_absx[-1][-7:] == ".ebuild":
+						del sp_absx[-1]
+						absx = "/".join(sp_absx)
+	
+					sp_absx_len = len(sp_absx)
+	
+					vdb_path = os.path.join(settings["ROOT"], portage.VDB_PATH)
+					vdb_len  = len(vdb_path)
+	
+					sp_vdb     = vdb_path.split("/")
+					sp_vdb_len = len(sp_vdb)
+	
+					if not os.path.exists(absx+"/CONTENTS"):
+						print "!!! Not a valid db dir: "+str(absx)
+						return 0
+	
+					if sp_absx_len <= sp_vdb_len:
+						# The Path is shorter... so it can't be inside the vdb.
+						print sp_absx
+						print absx
+						print "\n!!!",x,"cannot be inside "+ \
+							vdb_path+"; aborting.\n"
+						return 0
+	
+					for idx in range(0,sp_vdb_len):
+						if idx >= sp_absx_len or sp_vdb[idx] != sp_absx[idx]:
+							print sp_absx
+							print absx
+							print "\n!!!", x, "is not inside "+\
+								vdb_path+"; aborting.\n"
+							return 0
+	
+					print "="+"/".join(sp_absx[sp_vdb_len:])
+					candidate_catpkgs.append(
+						"="+"/".join(sp_absx[sp_vdb_len:]))
+	
+		newline=""
+		if (not "--quiet" in myopts):
+			newline="\n"
+		if settings["ROOT"] != "/":
+			print darkgreen(newline+ \
+				">>> Using system located in ROOT tree "+settings["ROOT"])
+		if (("--pretend" in myopts) or ("--ask" in myopts)) and \
+			not ("--quiet" in myopts):
+			print darkgreen(newline+\
+				">>> These are the packages that would be unmerged:")
+	
+		pkgmap={}
+		numselected=0
+		for x in candidate_catpkgs:
+			# cycle through all our candidate deps and determine
+			# what will and will not get unmerged
+			try:
+				mymatch=localtree.dep_match(x)
+			except KeyError:
+				mymatch=None
+			except ValueError, errpkgs:
+				print "\n\n!!! The short ebuild name \"" + \
+					x + "\" is ambiguous.  Please specify"
+				print "!!! one of the following fully-qualified " + \
+					"ebuild names instead:\n"
+				for i in errpkgs[0]:
+					print "    " + green(i)
+				print
+				sys.exit(1)
+	
+			if not mymatch and x[0] not in "<>=~":
+				#add a "=" if missing
+				mymatch=localtree.dep_match("="+x)
+			if not mymatch:
+				portage.writemsg("\n--- Couldn't find '%s' to %s.\n" % \
+					(x, unmerge_action), noiselevel=-1)
+				continue
+			mykey = portage.key_expand(
+				portage.dep_getkey(
+					mymatch[0]), mydb=vartree.dbapi, settings=settings)
+			if not pkgmap.has_key(mykey):
+				pkgmap[mykey]={"protected":[], "selected":[], "omitted":[] }
+			if unmerge_action=="unmerge":
+					for y in mymatch:
+						if y not in pkgmap[mykey]["selected"]:
+							pkgmap[mykey]["selected"].append(y)
+							numselected=numselected+len(mymatch)
+	
+			else:
+				#unmerge_action in ["prune", clean"]
+				slotmap={}
+				for mypkg in mymatch:
+					if unmerge_action=="clean":
+						myslot=localtree.getslot(mypkg)
+					else:
+						# since we're pruning, we don't care about slots
+						# and put all the pkgs in together
+						myslot=0
+					if not slotmap.has_key(myslot):
+						slotmap[myslot]={}
+					slotmap[myslot][localtree.dbapi.cpv_counter(mypkg)]=mypkg
+				for myslot in slotmap.keys():
+					counterkeys=slotmap[myslot].keys()
+					counterkeys.sort()
+					if not counterkeys:
+						continue
+					counterkeys.sort()
+					pkgmap[mykey]["protected"].append(
+						slotmap[myslot][counterkeys[-1]])
+					del counterkeys[-1]
+					#be pretty and get them in order of merge:
+					for ckey in counterkeys:
+						pkgmap[mykey]["selected"].append(slotmap[myslot][ckey])
+						numselected=numselected+1
+					# ok, now the last-merged package
+					# is protected, and the rest are selected
+		if global_unmerge and not numselected:
+			portage.writemsg_stdout("\n>>> No outdated packages were found on your system.\n")
+			return 0
+	
+		if not numselected:
+			portage.writemsg_stdout(
+				"\n>>> No packages selected for removal by " + \
+				unmerge_action + "\n")
+			return 0
+	finally:
+		if vdb_lock:
+			portage_locks.unlockdir(vdb_lock)
+	for x in pkgmap.keys():
+		for y in localtree.dep_match(x):
+			if y not in pkgmap[x]["omitted"] and \
+			   y not in pkgmap[x]["selected"] and \
+			   y not in pkgmap[x]["protected"]:
+				pkgmap[x]["omitted"].append(y)
+		if global_unmerge and not pkgmap[x]["selected"]:
+			#avoid cluttering the preview printout with stuff that isn't getting unmerged
+			continue
+		if not (pkgmap[x]["protected"] or pkgmap[x]["omitted"]) and (x in syslist):
+			print colorize("BAD","\a\n\n!!! '%s' is part of your system profile." % x)
+			print colorize("WARN","\a!!! Unmerging it may be damaging to your system.\n")
+			if "--pretend" not in myopts and "--ask" not in myopts:
+				countdown(int(settings["EMERGE_WARNING_DELAY"]),
+					colorize("UNMERGE_WARN", "Press Ctrl-C to Stop"))
+		print "\n "+white(x)
+		for mytype in ["selected","protected","omitted"]:
+			portage.writemsg_stdout((mytype + ": ").rjust(14), noiselevel=-1)
+			if pkgmap[x][mytype]:
+				for mypkg in pkgmap[x][mytype]:
+					mysplit=portage.catpkgsplit(mypkg)
+					if mysplit[3]=="r0":
+						myversion=mysplit[2]
+					else:
+						myversion=mysplit[2]+"-"+mysplit[3]
+					if mytype=="selected":
+						portage.writemsg_stdout(
+							colorize("UNMERGE_WARN", myversion + " "), noiselevel=-1)
+					else:
+						portage.writemsg_stdout(
+							colorize("GOOD", myversion + " "), noiselevel=-1)
+			else:
+				portage.writemsg_stdout("none", noiselevel=-1)
+			portage.writemsg_stdout("\n", noiselevel=-1)
+
+	portage.writemsg_stdout("\n>>> " + colorize("UNMERGE_WARN", "'Selected'") + \
+		" packages are slated for removal.\n")
+	portage.writemsg_stdout(">>> " + colorize("GOOD", "'Protected'") + \
+			" and " + colorize("GOOD", "'omitted'") + \
+			" packages will not be removed.\n\n")
+
+	if "--pretend" in myopts:
+		#we're done... return
+		return 0
+	if "--ask" in myopts:
+		if userquery("Would you like to unmerge these packages?")=="No":
+			# enter pretend mode for correct formatting of results
+			myopts["--pretend"] = True
+			print
+			print "Quitting."
+			print
+			return 0
+	#the real unmerging begins, after a short delay....
+	if not autoclean:
+		countdown(int(settings["CLEAN_DELAY"]), ">>> Unmerging")
+
+	for x in pkgmap.keys():
+		for y in pkgmap[x]["selected"]:
+			print ">>> Unmerging "+y+"..."
+			emergelog(xterm_titles, "=== Unmerging... ("+y+")")
+			mysplit=y.split("/")
+			#unmerge...
+			retval = portage.unmerge(mysplit[0], mysplit[1], settings["ROOT"],
+				mysettings, unmerge_action not in ["clean","prune"],
+				vartree=vartree, ldpath_mtimes=ldpath_mtimes)
+			if retval != os.EX_OK:
+				emergelog(xterm_titles, " !!! unmerge FAILURE: "+y)
+				ebuild = vartree.dbapi.findname(y)
+				show_unmerge_failure_message(y, ebuild, retval)
+				sys.exit(retval)
+			else:
+				clean_world(vartree.dbapi, y)
+				emergelog(xterm_titles, " >>> unmerge success: "+y)
+	return 1
+
+def show_unmerge_failure_message(pkg, ebuild, retval):
+
+	from formatter import AbstractFormatter, DumbWriter
+	f = AbstractFormatter(DumbWriter(sys.stderr, maxcol=72))
+
+	msg = []
+	msg.append("A removal phase of the '%s' package " % pkg)
+	msg.append("has failed with exit value %s.  " % retval)
+	msg.append("The problem occurred while executing ")
+	msg.append("the ebuild located at '%s'.  " % ebuild)
+	msg.append("If necessary, manually remove the ebuild " )
+	msg.append("in order to skip the execution of removal phases.")
+
+	f.end_paragraph(1)
+	for x in msg:
+		f.add_flowing_data(x)
+	f.end_paragraph(1)
+	f.writer.flush()
+
+def chk_updated_info_files(root, infodirs, prev_mtimes, retval):
+
+	if os.path.exists("/usr/bin/install-info"):
+		regen_infodirs=[]
+		for z in infodirs:
+			if z=='':
+				continue
+			inforoot=normpath(root+z)
+			if os.path.isdir(inforoot):
+				infomtime = long(os.stat(inforoot).st_mtime)
+				if inforoot not in prev_mtimes or \
+					prev_mtimes[inforoot] != infomtime:
+						regen_infodirs.append(inforoot)
+
+		if not regen_infodirs:
+			portage.writemsg_stdout(" "+green("*")+" GNU info directory index is up-to-date.\n")
+		else:
+			portage.writemsg_stdout(" "+green("*")+" Regenerating GNU info directory index...\n")
+
+			icount=0
+			badcount=0
+			for inforoot in regen_infodirs:
+				if inforoot=='':
+					continue
+				for filename in ("dir", "dir.gz", "dir.bz2"):
+					file_path = os.path.join(inforoot, filename)
+					try:
+						os.rename(file_path, file_path + ".old")
+					except OSError, e:
+						if e.errno != errno.ENOENT:
+							raise
+						del e
+
+				if not os.path.isdir(inforoot):
+					continue
+				errmsg = ""
+				file_list = os.listdir(inforoot)
+				file_list.sort()
+				for x in file_list:
+					if (x[0] == ".") or (x in ["dir","dir.old"]) or (os.path.isdir(inforoot+"/"+x)):
+						continue
+					myso=commands.getstatusoutput("LANG=C LANGUAGE=C /usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1]
+					existsstr="already exists, for file `"
+					if myso!="":
+						if re.search(existsstr,myso):
+							# Already exists... Don't increment the count for this.
+							pass
+						elif myso[:44]=="install-info: warning: no info dir entry in ":
+							# This info file doesn't contain a DIR-header: install-info produces this
+							# (harmless) warning (the --quiet switch doesn't seem to work).
+							# Don't increment the count for this.
+							pass
+						else:
+							badcount=badcount+1
+							errmsg += myso + "\n"
+					icount=icount+1
+
+				#update mtime so we can potentially avoid regenerating.
+				prev_mtimes[inforoot] = long(os.stat(inforoot).st_mtime)
+
+			if badcount:
+				print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors."
+				print errmsg
+			else:
+				print " "+green("*")+" Processed",icount,"info files."
+
+
+def post_emerge(settings, mtimedb, retval):
+	target_root = settings["ROOT"]
+	info_mtimes = mtimedb["info"]
+
+	# Load the most current variables from ${ROOT}/etc/profile.env
+	settings.unlock()
+	settings.regenerate()
+	settings.lock()
+
+	config_protect = settings.get("CONFIG_PROTECT","").split()
+	infodirs = settings.get("INFOPATH","").split(":") + \
+		settings.get("INFODIR","").split(":")
+
+	os.chdir("/")
+
+	emergelog("notitles" not in settings.features,
+		" *** exiting successfully.")
+
+	if "noinfo" not in settings.features:
+		chk_updated_info_files(target_root, infodirs, info_mtimes, retval)
+
+	chk_updated_cfg_files(target_root, config_protect)
+	mtimedb.commit()
+	sys.exit(retval)
+
+
+def chk_updated_cfg_files(target_root, config_protect):
+	if config_protect:
+		#number of directories with some protect files in them
+		procount=0
+		for x in config_protect:
+			x = os.path.join(target_root, x.lstrip(os.path.sep))
+			try:
+				mymode = os.lstat(x).st_mode
+			except OSError:
+				continue
+			if stat.S_ISDIR(mymode):
+				mycommand = "cd '%s'; find . -iname '._cfg????_*'" % x
+			else:
+				mycommand = "cd '%s'; find . -maxdepth 1 -iname '._cfg????_%s'" % \
+					os.path.split(x.rstrip(os.path.sep))
+			a = commands.getstatusoutput(mycommand + \
+				" ! -iname '.*~' ! -iname '.*.bak'")
+			if a[0] != 0:
+				print >> sys.stderr, " " + bad("*")+ " error scanning '%s'" % x
+			else:
+				files = a[1].split()
+				if files:
+					procount += 1
+					print colorize("WARN", " * IMPORTANT:"),
+					if stat.S_ISDIR(mymode):
+						 print "%d config files in '%s' need updating." % \
+							(len(files), x)
+					else:
+						 print "config file '%s' needs updating." % x
+
+		if procount:
+			#print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
+			print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
+
+def is_valid_package_atom(x):
+	try:
+		testkey = portage.dep_getkey(x)
+	except portage_exception.InvalidData:
+		return False
+	if testkey.startswith("null/"):
+		testatom = x.replace(testkey[5:], "cat/"+testkey[5:])
+	elif "/" not in x:
+		testatom = "cat/"+x
+	else:
+		testatom = x
+	return portage.isvalidatom(testatom)
+
+def validate_merge_list(trees, mergelist):
+	"""Validate the list to make sure all the packages are still available.
+	This is needed for --resume."""
+	for (pkg_type, myroot, pkg_key, action) in mergelist:
+		if pkg_type == "binary" and \
+			not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
+			pkg_type == "ebuild" and \
+			not trees[myroot]["porttree"].dbapi.xmatch(
+			"match-all", "="+pkg_key):
+			print red("!!! Error: The resume list contains packages that are no longer")
+			print red("!!!        available to be emerged. Please restart/continue")
+			print red("!!!        the merge operation manually.")
+			sys.exit(1)
+
+def show_blocker_docs_link():
+	print
+	print "For more information about " + bad("Blocked Packages") + ", please refer to the following"
+	print "section of the Gentoo Linux x86 Handbook (architecture is irrelevant):"
+	print
+	print "http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?full=1#blocked"
+	print
+
+def action_sync(settings, trees, mtimedb, myopts, myaction):
+	xterm_titles = "notitles" not in settings.features
+	emergelog(xterm_titles, " === sync")
+	myportdir = settings.get("PORTDIR", None)
+	if not myportdir:
+		sys.stderr.write("!!! PORTDIR is undefined.  Is /etc/make.globals missing?\n")
+		sys.exit(1)
+	if myportdir[-1]=="/":
+		myportdir=myportdir[:-1]
+	if not os.path.exists(myportdir):
+		print ">>>",myportdir,"not found, creating it."
+		os.makedirs(myportdir,0755)
+	syncuri=settings["SYNC"].rstrip()
+	os.umask(0022)
+	updatecache_flg = False
+	if myaction == "metadata":
+		print "skipping sync"
+		updatecache_flg = True
+		tmpservertimestampfile = None
+	elif syncuri[:8]=="rsync://":
+		if not os.path.exists("/usr/bin/rsync"):
+			print "!!! /usr/bin/rsync does not exist, so rsync support is disabled."
+			print "!!! Type \"emerge net-misc/rsync\" to enable rsync support."
+			sys.exit(1)
+		mytimeout=180
+
+		rsync_opts = []
+		import shlex, StringIO
+		if settings["PORTAGE_RSYNC_OPTS"] == "":
+			portage.writemsg("PORTAGE_RSYNC_OPTS empty or unset, using hardcoded defaults\n")
+			rsync_opts.extend([
+				"--recursive",    # Recurse directories
+				"--links",        # Consider symlinks
+				"--safe-links",   # Ignore links outside of tree
+				"--perms",        # Preserve permissions
+				"--times",        # Preserive mod times
+				"--compress",     # Compress the data transmitted
+				"--force",        # Force deletion on non-empty dirs
+				"--whole-file",   # Don't do block transfers, only entire files
+				"--delete",       # Delete files that aren't in the master tree
+				"--delete-after", # Delete only after everything else is done
+				"--stats",        # Show final statistics about what was transfered
+				"--timeout="+str(mytimeout), # IO timeout if not done in X seconds
+				"--exclude=/distfiles",   # Exclude distfiles from consideration
+				"--exclude=/local",       # Exclude local     from consideration
+				"--exclude=/packages",    # Exclude packages  from consideration
+				"--filter=H_**/files/digest-*", # Exclude manifest1 digests and delete on the receiving side
+			])
+
+		else:
+			# The below validation is not needed when using the above hardcoded
+			# defaults.
+
+			portage.writemsg("Using PORTAGE_RSYNC_OPTS instead of hardcoded defaults\n", 1)
+			lexer = shlex.shlex(StringIO.StringIO(
+				settings.get("PORTAGE_RSYNC_OPTS","")), posix=True)
+			lexer.whitespace_split = True
+			rsync_opts.extend(lexer)
+			del lexer
+
+			for opt in ("--recursive", "--times"):
+				if opt not in rsync_opts:
+					portage.writemsg(yellow("WARNING:") + " adding required option " + \
+					"%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
+					rsync_opts.append(opt)
+	
+			for exclude in ("distfiles", "local", "packages"):
+				opt = "--exclude=/%s" % exclude
+				if opt not in rsync_opts:
+					portage.writemsg(yellow("WARNING:") + \
+					" adding required option %s not included in "  % opt + \
+					"PORTAGE_RSYNC_OPTS (can be overridden with --exclude='!')\n")
+					rsync_opts.append(opt)
+	
+			if settings["RSYNC_TIMEOUT"] != "":
+				portage.writemsg("WARNING: usage of RSYNC_TIMEOUT is deprecated, " + \
+				"use PORTAGE_RSYNC_EXTRA_OPTS instead\n")
+				try:
+					mytimeout = int(settings["RSYNC_TIMEOUT"])
+					rsync_opts.append("--timeout=%d" % mytimeout)
+				except ValueError, e:
+					portage.writemsg("!!! %s\n" % str(e))
+	
+			# TODO: determine options required for official servers
+			if syncuri.rstrip("/").endswith(".gentoo.org/gentoo-portage"):
+
+				def rsync_opt_startswith(opt_prefix):
+					for x in rsync_opts:
+						if x.startswith(opt_prefix):
+							return True
+					return False
+
+				if not rsync_opt_startswith("--timeout="):
+					rsync_opts.append("--timeout=%d" % mytimeout)
+
+				for opt in ("--compress", "--whole-file"):
+					if opt not in rsync_opts:
+						portage.writemsg(yellow("WARNING:") + " adding required option " + \
+						"%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
+						rsync_opts.append(opt)
+
+		if "--quiet" in myopts:
+			rsync_opts.append("--quiet")    # Shut up a lot
+		else:
+			rsync_opts.append("--verbose")	# Print filelist
+
+		if "--verbose" in myopts:
+			rsync_opts.append("--progress")  # Progress meter for each file
+
+		if "--debug" in myopts:
+			rsync_opts.append("--checksum") # Force checksum on all files
+
+		if settings["RSYNC_EXCLUDEFROM"] != "":
+			portage.writemsg(yellow("WARNING:") + \
+			" usage of RSYNC_EXCLUDEFROM is deprecated, use " + \
+			"PORTAGE_RSYNC_EXTRA_OPTS instead\n")
+			if os.path.exists(settings["RSYNC_EXCLUDEFROM"]):
+				rsync_opts.append("--exclude-from=%s" % \
+				settings["RSYNC_EXCLUDEFROM"])
+			else:
+				portage.writemsg("!!! RSYNC_EXCLUDEFROM specified," + \
+				" but file does not exist.\n")
+
+		if settings["RSYNC_RATELIMIT"] != "":
+			portage.writemsg(yellow("WARNING:") + \
+			" usage of RSYNC_RATELIMIT is deprecated, use " + \
+			"PORTAGE_RSYNC_EXTRA_OPTS instead")
+			rsync_opts.append("--bwlimit=%s" % \
+			settings["RSYNC_RATELIMIT"])
+
+		# Real local timestamp file.
+		servertimestampfile = os.path.join(
+			myportdir, "metadata", "timestamp.chk")
+		# Temporary file for remote server timestamp comparison.
+		tmpservertimestampfile = os.path.join(
+			settings["PORTAGE_TMPDIR"], "timestamp.chk")
+
+		content = portage_util.grabfile(servertimestampfile)
+		mytimestamp = 0
+		if content:
+			try:
+				mytimestamp = time.mktime(time.strptime(content[0],
+					"%a, %d %b %Y %H:%M:%S +0000"))
+			except (OverflowError, ValueError):
+				pass
+		del content
+
+		try:
+			if settings.has_key("RSYNC_RETRIES"):
+				print yellow("WARNING:")+" usage of RSYNC_RETRIES is deprecated, use PORTAGE_RSYNC_RETRIES instead"
+				maxretries=int(settings["RSYNC_RETRIES"])				
+			else:
+				maxretries=int(settings["PORTAGE_RSYNC_RETRIES"])
+		except SystemExit, e:
+			raise # Needed else can't exit
+		except:
+			maxretries=3 #default number of retries
+
+		retries=0
+		user_name, hostname, port = re.split(
+			"rsync://([^:/]+@)?([^:/]*)(:[0-9]+)?", syncuri, maxsplit=3)[1:4]
+		if port is None:
+			port=""
+		if user_name is None:
+			user_name=""
+		updatecache_flg=True
+		all_rsync_opts = set(rsync_opts)
+		lexer = shlex.shlex(StringIO.StringIO(
+			settings.get("PORTAGE_RSYNC_EXTRA_OPTS","")), posix=True)
+		lexer.whitespace_split = True
+		extra_rsync_opts = list(lexer)
+		del lexer
+		all_rsync_opts.update(extra_rsync_opts)
+		family = socket.AF_INET
+		if "-4" in all_rsync_opts or "--ipv4" in all_rsync_opts:
+			family = socket.AF_INET
+		elif socket.has_ipv6 and \
+			("-6" in all_rsync_opts or "--ipv6" in all_rsync_opts):
+			family = socket.AF_INET6
+		ips=[]
+		while (1):
+			if ips:
+				del ips[0]
+			if ips==[]:
+				try:
+					for addrinfo in socket.getaddrinfo(
+						hostname, None, family, socket.SOCK_STREAM):
+						if addrinfo[0] == socket.AF_INET6:
+							# IPv6 addresses need to be enclosed in square brackets
+							ips.append("[%s]" % addrinfo[4][0])
+						else:
+							ips.append(addrinfo[4][0])
+					from random import shuffle
+					shuffle(ips)
+				except SystemExit, e:
+					raise # Needed else can't exit
+				except Exception, e:
+					print "Notice:",str(e)
+					dosyncuri=syncuri
+
+			if ips:
+				try:
+					dosyncuri = syncuri.replace(
+						"//" + user_name + hostname + port + "/",
+						"//" + user_name + ips[0] + port + "/", 1)
+				except SystemExit, e:
+					raise # Needed else can't exit
+				except Exception, e:
+					print "Notice:",str(e)
+					dosyncuri=syncuri
+
+			if (retries==0):
+				if "--ask" in myopts:
+					if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No":
+						print
+						print "Quitting."
+						print
+						sys.exit(0)
+				emergelog(xterm_titles, ">>> Starting rsync with " + dosyncuri)
+				if "--quiet" not in myopts:
+					print ">>> Starting rsync with "+dosyncuri+"..."
+			else:
+				emergelog(xterm_titles,
+					">>> Starting retry %d of %d with %s" % \
+						(retries,maxretries,dosyncuri))
+				print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri)
+
+			if mytimestamp != 0 and "--quiet" not in myopts:
+				print ">>> Checking server timestamp ..."
+
+			rsynccommand = ["/usr/bin/rsync"] + rsync_opts + extra_rsync_opts
+
+			if "--debug" in myopts:
+				print rsynccommand
+
+			exitcode = os.EX_OK
+			servertimestamp = 0
+			# Even if there's no timestamp available locally, fetch the
+			# timestamp anyway as an initial probe to verify that the server is
+			# responsive.  This protects us from hanging indefinitely on a
+			# connection attempt to an unresponsive server which rsync's
+			# --timeout option does not prevent.
+			if True:
+				mycommand = rsynccommand[:]
+				mycommand.append(dosyncuri.rstrip("/") + \
+					"/metadata/timestamp.chk")
+				mycommand.append(tmpservertimestampfile)
+				import portage_exec
+				content = None
+				mypids = []
+				try:
+					def timeout_handler(signum, frame):
+						raise portage_exception.PortageException("timed out")
+					signal.signal(signal.SIGALRM, timeout_handler)
+					# Timeout here in case the server is unresponsive.  The
+					# --timeout rsync option doesn't apply to the initial
+					# connection attempt.
+					signal.alarm(15)
+					try:
+						mypids.extend(portage_exec.spawn(
+							mycommand, env=settings.environ(), returnpid=True))
+						exitcode = os.waitpid(mypids[0], 0)[1]
+						content = portage.grabfile(tmpservertimestampfile)
+					finally:
+						signal.alarm(0)
+						try:
+							os.unlink(tmpservertimestampfile)
+						except OSError:
+							pass
+				except portage_exception.PortageException, e:
+					# timed out
+					print e
+					del e
+					if mypids and os.waitpid(mypids[0], os.WNOHANG) == (0,0):
+						os.kill(mypids[0], signal.SIGTERM)
+						os.waitpid(mypids[0], 0)
+					# This is the same code rsync uses for timeout.
+					exitcode = 30
+				else:
+					if exitcode != os.EX_OK:
+						if exitcode & 0xff:
+							exitcode = (exitcode & 0xff) << 8
+						else:
+							exitcode = exitcode >> 8
+				if mypids:
+					portage_exec.spawned_pids.remove(mypids[0])
+				if content:
+					try:
+						servertimestamp = time.mktime(time.strptime(
+							content[0], "%a, %d %b %Y %H:%M:%S +0000"))
+					except (OverflowError, ValueError):
+						pass
+				del mycommand, mypids, content
+			if exitcode == os.EX_OK:
+				if (servertimestamp != 0) and (servertimestamp == mytimestamp):
+					emergelog(xterm_titles,
+						">>> Cancelling sync -- Already current.")
+					print
+					print ">>>"
+					print ">>> Timestamps on the server and in the local repository are the same."
+					print ">>> Cancelling all further sync action. You are already up to date."
+					print ">>>"
+					print ">>> In order to force sync, remove '%s'." % servertimestampfile
+					print ">>>"
+					print
+					sys.exit(0)
+				elif (servertimestamp != 0) and (servertimestamp < mytimestamp):
+					emergelog(xterm_titles,
+						">>> Server out of date: %s" % dosyncuri)
+					print
+					print ">>>"
+					print ">>> SERVER OUT OF DATE: %s" % dosyncuri
+					print ">>>"
+					print ">>> In order to force sync, remove '%s'." % servertimestampfile
+					print ">>>"
+					print
+				elif (servertimestamp == 0) or (servertimestamp > mytimestamp):
+					# actual sync
+					mycommand = rsynccommand + [dosyncuri+"/", myportdir]
+					exitcode = portage.portage_exec.spawn(mycommand,
+						env=settings.environ())
+					if exitcode in [0,1,3,4,11,14,20,21]:
+						break
+			elif exitcode in [1,3,4,11,14,20,21]:
+				break
+			else:
+				# Code 2 indicates protocol incompatibility, which is expected
+				# for servers with protocol < 29 that don't support
+				# --prune-empty-directories.  Retry for a server that supports
+				# at least rsync protocol version 29 (>=rsync-2.6.4).
+				pass
+
+			retries=retries+1
+
+			if retries<=maxretries:
+				print ">>> Retrying..."
+				time.sleep(11)
+			else:
+				# over retries
+				# exit loop
+				updatecache_flg=False
+				break
+
+		if (exitcode==0):
+			emergelog(xterm_titles, "=== Sync completed with %s" % dosyncuri)
+		elif (exitcode>0):
+			print
+			if exitcode==1:
+				print darkred("!!!")+green(" Rsync has reported that there is a syntax error. Please ensure")
+				print darkred("!!!")+green(" that your SYNC statement is proper.")
+				print darkred("!!!")+green(" SYNC="+settings["SYNC"])
+			elif exitcode==11:
+				print darkred("!!!")+green(" Rsync has reported that there is a File IO error. Normally")
+				print darkred("!!!")+green(" this means your disk is full, but can be caused by corruption")
+				print darkred("!!!")+green(" on the filesystem that contains PORTDIR. Please investigate")
+				print darkred("!!!")+green(" and try again after the problem has been fixed.")
+				print darkred("!!!")+green(" PORTDIR="+settings["PORTDIR"])
+			elif exitcode==20:
+				print darkred("!!!")+green(" Rsync was killed before it finished.")
+			else:
+				print darkred("!!!")+green(" Rsync has not successfully finished. It is recommended that you keep")
+				print darkred("!!!")+green(" trying or that you use the 'emerge-webrsync' option if you are unable")
+				print darkred("!!!")+green(" to use rsync due to firewall or other restrictions. This should be a")
+				print darkred("!!!")+green(" temporary problem unless complications exist with your network")
+				print darkred("!!!")+green(" (and possibly your system's filesystem) configuration.")
+			print
+			sys.exit(exitcode)
+	elif syncuri[:6]=="cvs://":
+		if not os.path.exists("/usr/bin/cvs"):
+			print "!!! /usr/bin/cvs does not exist, so CVS support is disabled."
+			print "!!! Type \"emerge dev-util/cvs\" to enable CVS support."
+			sys.exit(1)
+		cvsroot=syncuri[6:]
+		cvsdir=os.path.dirname(myportdir)
+		if not os.path.exists(myportdir+"/CVS"):
+			#initial checkout
+			print ">>> Starting initial cvs checkout with "+syncuri+"..."
+			if os.path.exists(cvsdir+"/gentoo-x86"):
+				print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting."
+				sys.exit(1)
+			try:
+				os.rmdir(myportdir)
+			except OSError, e:
+				if e.errno != errno.ENOENT:
+					sys.stderr.write(
+						"!!! existing '%s' directory; exiting.\n" % myportdir)
+					sys.exit(1)
+				del e
+			if portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",settings,free=1):
+				print "!!! cvs checkout error; exiting."
+				sys.exit(1)
+			os.rename(os.path.join(cvsdir, "gentoo-x86"), myportdir)
+		else:
+			#cvs update
+			print ">>> Starting cvs update with "+syncuri+"..."
+			retval = portage.spawn("cd '%s'; cvs -z0 -q update -dP" % \
+				myportdir, settings, free=1)
+			if retval != os.EX_OK:
+				sys.exit(retval)
+		dosyncuri = syncuri
+	else:
+		print "!!! rsync setting: ",syncuri,"not recognized; exiting."
+		sys.exit(1)
+
+	if updatecache_flg and  \
+		myaction != "metadata" and \
+		"metadata-transfer" not in settings.features:
+		updatecache_flg = False
+
+	# Reload the whole config from scratch.
+	settings, trees, mtimedb = load_emerge_config(trees=trees)
+	portdb = trees[settings["ROOT"]]["porttree"].dbapi
+
+	if os.path.exists(myportdir+"/metadata/cache") and updatecache_flg:
+		action_metadata(settings, portdb, myopts)
+
+	if portage.global_updates(settings, trees, mtimedb["updates"]):
+		mtimedb.commit()
+		# Reload the whole config from scratch.
+		settings, trees, mtimedb = load_emerge_config(trees=trees)
+		portdb = trees[settings["ROOT"]]["porttree"].dbapi
+
+	mybestpv = portdb.xmatch("bestmatch-visible", "sys-apps/portage")
+	mypvs = portage.best(
+		trees[settings["ROOT"]]["vartree"].dbapi.match("sys-apps/portage"))
+
+	chk_updated_cfg_files("/", settings.get("CONFIG_PROTECT","").split())
+
+	if myaction != "metadata":
+		if os.access(portage.USER_CONFIG_PATH + "/bin/post_sync", os.X_OK):
+			retval = portage.portage_exec.spawn(
+				[os.path.join(portage.USER_CONFIG_PATH, "bin", "post_sync"),
+				dosyncuri], env=settings.environ())
+			if retval != os.EX_OK:
+				print red(" * ")+bold("spawn failed of "+ portage.USER_CONFIG_PATH + "/bin/post_sync")
+
+	if(mybestpv != mypvs) and not "--quiet" in myopts:
+		print
+		print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended"
+		print red(" * ")+"that you update portage now, before any other packages are updated."
+		print red(" * ")+"Please run 'emerge portage' and then update "+bold("ALL")+" of your"
+		print red(" * ")+"configuration files."
+		print red(" * ")+"To update portage, run 'emerge portage'."
+		print
+
+def action_metadata(settings, portdb, myopts):
+	portage.writemsg_stdout("\n>>> Updating Portage cache:      ")
+	old_umask = os.umask(0002)
+	cachedir = os.path.normpath(settings.depcachedir)
+	if cachedir in ["/",    "/bin", "/dev",  "/etc",  "/home",
+					"/lib", "/opt", "/proc", "/root", "/sbin",
+					"/sys", "/tmp", "/usr",  "/var"]:
+		print >> sys.stderr, "!!! PORTAGE_DEPCACHEDIR IS SET TO A PRIMARY " + \
+			"ROOT DIRECTORY ON YOUR SYSTEM."
+		print >> sys.stderr, \
+			"!!! This is ALMOST CERTAINLY NOT what you want: '%s'" % cachedir
+		sys.exit(73)
+	if not os.path.exists(cachedir):
+		os.mkdir(cachedir)
+
+	ec = portage.eclass_cache.cache(portdb.porttree_root)
+	myportdir = os.path.realpath(settings["PORTDIR"])
+	cm = settings.load_best_module("portdbapi.metadbmodule")(
+		myportdir, "metadata/cache", portage.auxdbkeys[:])
+
+	import cache.util
+
+	class percentage_noise_maker(cache.util.quiet_mirroring):
+		def __init__(self, dbapi):
+			self.dbapi = dbapi
+			self.cp_all = dbapi.cp_all()
+			l = len(self.cp_all)
+			self.call_update_min = 100000000
+			self.min_cp_all = l/100.0
+			self.count = 1
+			self.pstr = ''
+
+		def __iter__(self):
+			for x in self.cp_all:
+				self.count += 1
+				if self.count > self.min_cp_all:
+					self.call_update_min = 0
+					self.count = 0
+				for y in self.dbapi.cp_list(x):
+					yield y
+			self.call_update_mine = 0
+
+		def update(self, *arg):
+			try:				self.pstr = int(self.pstr) + 1
+			except ValueError:	self.pstr = 1
+			sys.stdout.write("%s%i%%" % \
+				("\b" * (len(str(self.pstr))+1), self.pstr))
+			sys.stdout.flush()
+			self.call_update_min = 10000000
+
+		def finish(self, *arg):
+			sys.stdout.write("\b\b\b\b100%\n")
+			sys.stdout.flush()
+
+	if "--quiet" in myopts:
+		def quicky_cpv_generator(cp_all_list):
+			for x in cp_all_list:
+				for y in portdb.cp_list(x):
+					yield y
+		source = quicky_cpv_generator(portdb.cp_all())
+		noise_maker = cache.util.quiet_mirroring()
+	else:
+		noise_maker = source = percentage_noise_maker(portdb)
+	cache.util.mirror_cache(source, cm, portdb.auxdb[myportdir],
+		eclass_cache=ec, verbose_instance=noise_maker)
+
+	sys.stdout.flush()
+	os.umask(old_umask)
+
+def action_regen(settings, portdb):
+	xterm_titles = "notitles" not in settings.features
+	emergelog(xterm_titles, " === regen")
+	#regenerate cache entries
+	print "Regenerating cache entries... "
+	try:
+		os.close(sys.stdin.fileno())
+	except SystemExit, e:
+		raise # Needed else can't exit
+	except:
+		pass
+	sys.stdout.flush()
+	mynodes = portdb.cp_all()
+	from cache.cache_errors import CacheError
+	dead_nodes = {}
+	for mytree in portdb.porttrees:
+		try:
+			dead_nodes[mytree] = set(portdb.auxdb[mytree].iterkeys())
+		except CacheError, e:
+			print "\n  error listing cache entries for " + \
+				"'%s': %s, continuing..." % (mytree, e)
+			del e
+			dead_nodes = None
+			break
+	for x in mynodes:
+		mymatches = portdb.cp_list(x)
+		portage.writemsg_stdout("processing %s\n" % x)
+		for y in mymatches:
+			try:
+				foo = portdb.aux_get(y,["DEPEND"])
+			except SystemExit, e:
+				# sys.exit is an exception... And consequently, we can't catch it.
+				raise
+			except Exception, e:
+				print "\n  error processing %(cpv)s, continuing... (%(e)s)" % {"cpv":y,"e":str(e)}
+			if dead_nodes:
+				for mytree in portdb.porttrees:
+					if portdb.findname2(y, mytree=mytree)[0]:
+						dead_nodes[mytree].discard(y)
+	if dead_nodes:
+		for mytree, nodes in dead_nodes.iteritems():
+			auxdb = portdb.auxdb[mytree]
+			for y in nodes:
+				try:
+					del auxdb[y]
+				except (KeyError, CacheError):
+					pass
+	print "done!"
+
+def action_config(settings, trees, myopts, myfiles):
+	if len(myfiles) != 1 or "system" in myfiles or "world" in myfiles:
+		print red("!!! config can only take a single package atom at this time\n")
+		sys.exit(1)
+	if not is_valid_package_atom(myfiles[0]):
+		portage.writemsg("!!! '%s' is not a valid package atom.\n" % myfiles[0],
+			noiselevel=-1)
+		portage.writemsg("!!! Please check ebuild(5) for full details.\n")
+		portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
+		sys.exit(1)
+	print
+	try:
+		pkgs = trees[settings["ROOT"]]["vartree"].dbapi.match(myfiles[0])
+	except ValueError, e:
+		# Multiple matches thrown from cpv_expand
+		pkgs = e.args[0]
+	if len(pkgs) == 0:
+		print "No packages found.\n"
+		sys.exit(0)
+	elif len(pkgs) > 1:
+		if "--ask" in myopts:
+			options = []
+			print "Please select a package to configure:"
+			idx = 0
+			for pkg in pkgs:
+				idx += 1
+				options.append(str(idx))
+				print options[-1]+") "+pkg
+			print "X) Cancel"
+			options.append("X")
+			idx = userquery("Selection?", options)
+			if idx == "X":
+				sys.exit(0)
+			pkg = pkgs[int(idx)-1]
+		else:
+			print "The following packages available:"
+			for pkg in pkgs:
+				print "* "+pkg
+			print "\nPlease use a specific atom or the --ask option."
+			sys.exit(1)
+	else:
+		pkg = pkgs[0]
+
+	print
+	if "--ask" in myopts:
+		if userquery("Ready to configure "+pkg+"?") == "No":
+			sys.exit(0)
+	else:
+		print "Configuring pkg..."
+	print
+	ebuildpath = trees[settings["ROOT"]]["vartree"].dbapi.findname(pkg)
+	mysettings = portage.config(clone=settings)
+	portage.doebuild(ebuildpath, "config", settings["ROOT"], mysettings,
+		debug=(settings.get("PORTAGE_DEBUG", "") == 1), cleanup=True,
+		mydbapi=trees[settings["ROOT"]]["vartree"].dbapi, tree="vartree")
+	print
+
+def action_info(settings, trees, myopts, myfiles):
+	unameout=commands.getstatusoutput("uname -mrp")[1]
+	print getportageversion(settings["PORTDIR"], settings["ROOT"],
+		settings.profile_path, settings["CHOST"],
+		trees[settings["ROOT"]]["vartree"].dbapi)
+	header_width = 65
+	header_title = "System Settings"
+	if myfiles:
+		print header_width * "="
+		print header_title.rjust(int(header_width/2 + len(header_title)/2))
+	print header_width * "="
+	print "System uname: "+unameout
+	gentoo_release = portage.grabfile(os.path.join(
+		settings["PORTAGE_CONFIGROOT"], "etc", "gentoo-release"))
+	if gentoo_release:
+		print gentoo_release[0]
+	else:
+		print "Unknown Host Operating System"
+	lastSync = portage.grabfile(os.path.join(
+		settings["PORTDIR"], "metadata", "timestamp.chk"))
+	print "Timestamp of tree:",
+	if lastSync:
+		print lastSync[0]
+	else:
+		print "Unknown"
+
+	output=commands.getstatusoutput("distcc --version")
+	if not output[0]:
+		print str(output[1].split("\n",1)[0]),
+		if "distcc" in settings.features:
+			print "[enabled]"
+		else:
+			print "[disabled]"
+
+	output=commands.getstatusoutput("ccache -V")
+	if not output[0]:
+		print str(output[1].split("\n",1)[0]),
+		if "ccache" in settings.features:
+			print "[enabled]"
+		else:
+			print "[disabled]"
+
+	myvars  = ["sys-devel/autoconf", "sys-devel/automake", "virtual/os-headers",
+	           "sys-devel/binutils", "sys-devel/libtool",  "dev-lang/python"]
+	myvars += portage_util.grabfile(settings["PORTDIR"]+"/profiles/info_pkgs")
+	myvars  = portage_util.unique_array(myvars)
+	myvars.sort()
+
+	for x in myvars:
+		if portage.isvalidatom(x):
+			pkg_matches = trees["/"]["vartree"].dbapi.match(x)
+			pkg_matches = [portage.catpkgsplit(cpv)[1:] for cpv in pkg_matches]
+			pkg_matches.sort(portage.pkgcmp)
+			pkgs = []
+			for pn, ver, rev in pkg_matches:
+				if rev != "r0":
+					pkgs.append(ver + "-" + rev)
+				else:
+					pkgs.append(ver)
+			if pkgs:
+				pkgs = ", ".join(pkgs)
+				print "%-20s %s" % (x+":", pkgs)
+		else:
+			print "%-20s %s" % (x+":", "[NOT VALID]")
+
+	libtool_vers = ",".join(trees["/"]["vartree"].dbapi.match("sys-devel/libtool"))
+
+	if "--verbose" in myopts:
+		myvars=settings.keys()
+	else:
+		myvars = ['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK',
+		          'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR',
+		          'PORTDIR_OVERLAY', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS',
+		          'ACCEPT_KEYWORDS', 'SYNC', 'FEATURES', 'EMERGE_DEFAULT_OPTS']
+
+		myvars.extend(portage_util.grabfile(settings["PORTDIR"]+"/profiles/info_vars"))
+
+	myvars = portage_util.unique_array(myvars)
+	unset_vars = []
+	myvars.sort()
+	for x in myvars:
+		if x in settings:
+			if x != "USE":
+				print '%s="%s"' % (x, settings[x])
+			else:
+				use = set(settings["USE"].split())
+				use_expand = settings["USE_EXPAND"].split()
+				use_expand.sort()
+				for varname in use_expand:
+					flag_prefix = varname.lower() + "_"
+					for f in list(use):
+						if f.startswith(flag_prefix):
+							use.remove(f)
+				use = list(use)
+				use.sort()
+				print 'USE="%s"' % " ".join(use),
+				for varname in use_expand:
+					myval = settings.get(varname)
+					if myval:
+						print '%s="%s"' % (varname, myval),
+				print
+		else:
+			unset_vars.append(x)
+	if unset_vars:
+		print "Unset:  "+", ".join(unset_vars)
+	print
+
+	if "--debug" in myopts:
+		for x in dir(portage):
+			module = getattr(portage, x)
+			if "cvs_id_string" in dir(module):
+				print "%s: %s" % (str(x), str(module.cvs_id_string))
+
+	# See if we can find any packages installed matching the strings
+	# passed on the command line
+	mypkgs = []
+	vardb = trees[settings["ROOT"]]["vartree"].dbapi
+	portdb = trees[settings["ROOT"]]["porttree"].dbapi
+	for x in myfiles:
+		mypkgs.extend(vardb.match(x))
+
+	# If some packages were found...
+	if mypkgs:
+		# Get our global settings (we only print stuff if it varies from
+		# the current config)
+		mydesiredvars = [ 'CHOST', 'CFLAGS', 'CXXFLAGS' ]
+		auxkeys = mydesiredvars + [ "USE", "IUSE"]
+		global_vals = {}
+		pkgsettings = portage.config(clone=settings)
+
+		for myvar in mydesiredvars:
+			global_vals[myvar] = set(settings.get(myvar, "").split())
+
+		# Loop through each package
+		# Only print settings if they differ from global settings
+		header_printed = False
+		for pkg in mypkgs:
+			# Get all package specific variables
+			auxvalues = vardb.aux_get(pkg, auxkeys)
+			valuesmap = {}
+			for i in xrange(len(auxkeys)):
+				valuesmap[auxkeys[i]] = set(auxvalues[i].split())
+			diff_values = {}
+			for myvar in mydesiredvars:
+				# If the package variable doesn't match the
+				# current global variable, something has changed
+				# so set diff_found so we know to print
+				if valuesmap[myvar] != global_vals[myvar]:
+					diff_values[myvar] = valuesmap[myvar]
+			valuesmap["IUSE"] = set(filter_iuse_defaults(valuesmap["IUSE"]))
+			valuesmap["USE"] = valuesmap["USE"].intersection(valuesmap["IUSE"])
+			pkgsettings.reset()
+			# If a matching ebuild is no longer available in the tree, maybe it
+			# would make sense to compare against the flags for the best
+			# available version with the same slot?
+			mydb = None
+			if portdb.cpv_exists(pkg):
+				mydb = portdb
+			pkgsettings.setcpv(pkg, mydb=mydb)
+			if valuesmap["IUSE"].intersection(pkgsettings["USE"].split()) != \
+				valuesmap["USE"]:
+				diff_values["USE"] = valuesmap["USE"]
+			# If a difference was found, print the info for
+			# this package.
+			if diff_values:
+
+				# If we have not yet printed the header, 
+				# print it now
+				if not header_printed:
+					header_title = "Package Settings"
+					print header_width * "="
+					print header_title.rjust(int(header_width/2 + len(header_title)/2))
+					print header_width * "="
+					header_printed = True
+
+				# Print package info
+				print "%s was built with the following:" % pkg
+				for myvar in mydesiredvars + ["USE"]:
+					if myvar in diff_values:
+						mylist = list(diff_values[myvar])
+						mylist.sort()
+						print "%s=\"%s\"" % (myvar, " ".join(mylist))
+				print
+
+def action_search(settings, portdb, vartree, myopts, myfiles, spinner):
+	if not myfiles:
+		print "emerge: no search terms provided."
+	else:
+		searchinstance = search(settings, portdb,
+			vartree, spinner, "--searchdesc" in myopts,
+			"--quiet" not in myopts)
+		for mysearch in myfiles:
+			try:
+				searchinstance.execute(mysearch)
+			except re.error, comment:
+				print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment )
+				sys.exit(1)
+			searchinstance.output()
+
+def action_depclean(settings, trees, ldpath_mtimes,
+	myopts, spinner):
+	# Kill packages that aren't explicitly merged or are required as a
+	# dependency of another package. World file is explicit.
+
+	warn_prefix = colorize("BAD", "*** WARNING ***  ")
+	print
+	print warn_prefix + "Depclean may break link level dependencies.  Thus, it is"
+	print warn_prefix + "recommended to use a tool such as " + good("`revdep-rebuild`") + " (from"
+	print warn_prefix + "app-portage/gentoolkit) in order to detect such breakage."
+	print warn_prefix
+	print warn_prefix + "Also study the list of packages to be cleaned for any obvious"
+	print warn_prefix + "mistakes. Packages that are part of the world set will always"
+	print warn_prefix + "be kept.  They can be manually added to this set with"
+	print warn_prefix + good("`emerge --noreplace <atom>`") + ".  Packages that are listed in"
+	print warn_prefix + "package.provided (see portage(5)) will be removed by"
+	print warn_prefix + "depclean, even if they are part of the world set."
+	print warn_prefix
+	print warn_prefix + "As a safety measure, depclean will not remove any packages"
+	print warn_prefix + "unless *all* required dependencies have been resolved.  As a"
+	print warn_prefix + "consequence, it is often necessary to run "
+	print warn_prefix + good("`emerge --update --newuse --deep world`") + " prior to depclean."
+
+	xterm_titles = "notitles" not in settings.features
+	myroot = settings["ROOT"]
+	dep_check_trees = {}
+	dep_check_trees[myroot] = {}
+	dep_check_trees[myroot]["vartree"] = \
+		FakeVartree(trees[myroot]["vartree"], trees[myroot]["porttree"].dbapi)
+	vardb = dep_check_trees[myroot]["vartree"].dbapi
+	# Constrain dependency selection to the installed packages.
+	dep_check_trees[myroot]["porttree"] = dep_check_trees[myroot]["vartree"]
+	syslist = getlist(settings, "system")
+	worldlist = getlist(settings, "world")
+	system_world_dict = genericdict(worldlist)
+	system_world_dict.update(genericdict(syslist))
+	fakedb = portage.fakedbapi(settings=settings)
+	myvarlist = vardb.cpv_all()
+
+	if not syslist:
+		print "\n!!! You have no system list.",
+	if not worldlist:
+		print "\n!!! You have no world file.",
+	if not myvarlist:
+		print "\n!!! You have no installed package database (%s)." % portage.VDB_PATH,
+
+	if not (syslist and worldlist and myvarlist):
+		print "\n!!! Proceeding "+(syslist and myvarlist and "may" or "will")
+		print " break your installation.\n"
+		if "--pretend" not in myopts:
+			countdown(int(settings["EMERGE_WARNING_DELAY"]), ">>> Depclean")
+
+	if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
+		emergelog(xterm_titles, " >>> depclean")
+
+	if "--quiet" not in myopts:
+		print "\nCalculating dependencies  ",
+
+	soft = 0
+	hard = 1
+	remaining_atoms = [(atom, 'world', hard) for atom in worldlist if vardb.match(atom)]
+	remaining_atoms += [(atom, 'system', hard) for atom in syslist if vardb.match(atom)]
+	unresolveable = {}
+	aux_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
+
+	while remaining_atoms:
+		atom, parent, priority = remaining_atoms.pop()
+		pkgs = vardb.match(atom)
+		if not pkgs:
+			if not atom.startswith("!") and priority == hard:
+				unresolveable.setdefault(atom, []).append(parent)
+			continue
+		if portage.dep_getkey(atom) not in system_world_dict:
+			# Prune all but the best matching slot, since that's all that a
+			# deep world update would pull in.  Don't prune if the cpv is in
+			# system or world though, since those sets trigger greedy update
+			# of all slots.
+			pkgs = [portage.best(pkgs)]
+		for pkg in pkgs:
+			if fakedb.cpv_exists(pkg):
+				continue
+			spinner.update()
+			fakedb.cpv_inject(pkg)
+			myaux = dict(izip(aux_keys, vardb.aux_get(pkg, aux_keys)))
+			mydeps = []
+			if myopts.get("--with-bdeps", "y") == "y":
+				mydeps.append((myaux["DEPEND"], soft))
+			del myaux["DEPEND"]
+			mydeps.append((" ".join(myaux.values()), hard))
+			usedef = vardb.aux_get(pkg, ["USE"])[0].split()
+			for depstr, priority in mydeps:
+
+				if not depstr:
+					continue
+
+				if "--debug" in myopts:
+					print
+					print "Parent:   ", pkg
+					print "Depstring:", depstr
+					print "Priority:",
+					if priority == soft:
+						print "soft"
+					else:
+						print "hard"
+
+				try:
+					portage_dep._dep_check_strict = False
+					success, atoms = portage.dep_check(depstr, None, settings,
+						myuse=usedef, trees=dep_check_trees, myroot=myroot)
+				finally:
+					portage_dep._dep_check_strict = True
+				if not success:
+					show_invalid_depstring_notice(
+						("installed", myroot, pkg, "nomerge"),
+						depstr, atoms)
+					return
+
+				if "--debug" in myopts:
+					print "Candidates:", atoms
+
+				for atom in atoms:
+					remaining_atoms.append((atom, pkg, priority))
+
+	if "--quiet" not in myopts:
+		print "\b\b... done!\n"
+
+	if unresolveable:
+		print "Dependencies could not be completely resolved due to"
+		print "the following required packages not being installed:"
+		print
+		for atom in unresolveable:
+			print atom, "required by", " ".join(unresolveable[atom])
+		print
+		print "Have you forgotten to run " + good("`emerge --update --newuse --deep world`") + " prior to"
+		print "depclean?  It may be necessary to manually uninstall packages that no longer"
+		print "exist in the portage tree since it may not be possible to satisfy their"
+		print "dependencies.  Also, be aware of the --with-bdeps option that is documented"
+		print "in " + good("`man emerge`") + "."
+		print
+		return
+
+	cleanlist = [pkg for pkg in vardb.cpv_all() if not fakedb.cpv_exists(pkg)]
+
+	if len(cleanlist):
+		unmerge(settings, myopts, trees[settings["ROOT"]]["vartree"],
+			"unmerge", cleanlist, ldpath_mtimes)
+
+	print "Packages installed:   "+str(len(myvarlist))
+	print "Packages in world:    "+str(len(worldlist))
+	print "Packages in system:   "+str(len(syslist))
+	print "Unique package names: "+str(len(myvarlist))
+	print "Required packages:    "+str(len(fakedb.cpv_all()))
+	if "--pretend" in myopts:
+		print "Number to remove:     "+str(len(cleanlist))
+	else:
+		print "Number removed:       "+str(len(cleanlist))
+
+def action_build(settings, trees, mtimedb,
+	myopts, myaction, myfiles, spinner):
+	ldpath_mtimes = mtimedb["ldpath"]
+	favorites=[]
+	if "--quiet" not in myopts and \
+		("--pretend" in myopts or "--ask" in myopts or \
+		"--tree" in myopts or "--verbose" in myopts):
+		action = ""
+		if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
+			action = "fetched"
+		else:
+			action = "merged"
+		if "--tree" in myopts and action != "fetched": # Tree doesn't work with fetching
+			print
+			print darkgreen("These are the packages that would be %s, in reverse order:") % action
+			print
+		else:
+			print
+			print darkgreen("These are the packages that would be %s, in order:") % action
+			print
+
+	# validate the state of the resume data
+	# so that we can make assumptions later.
+	for k in ("resume", "resume_backup"):
+		if k in mtimedb:
+			if "mergelist" in mtimedb[k]:
+				if not mtimedb[k]["mergelist"]:
+					del mtimedb[k]
+			else:
+				del mtimedb[k]
+
+	if "--resume" in myopts and \
+		("resume" in mtimedb or
+		"resume_backup" in mtimedb):
+		if "resume" not in mtimedb:
+			mtimedb["resume"] = mtimedb["resume_backup"]
+			del mtimedb["resume_backup"]
+			mtimedb.commit()
+		# XXX: "myopts" is a list for backward compatibility.
+		myresumeopts = dict([(k,True) for k in mtimedb["resume"]["myopts"]])
+
+		for opt in ("--skipfirst", "--ask", "--tree"):
+			myresumeopts.pop(opt, None)
+
+		for myopt, myarg in myopts.iteritems():
+			if myopt not in myresumeopts:
+				myresumeopts[myopt] = myarg
+		myopts=myresumeopts
+
+		# Adjust config according to options of the command being resumed.
+		for myroot in trees:
+			mysettings =  trees[myroot]["vartree"].settings
+			mysettings.unlock()
+			adjust_config(myopts, mysettings)
+			mysettings.lock()
+			del myroot, mysettings
+
+		myparams = create_depgraph_params(myopts, myaction)
+		if "--quiet" not in myopts and "--nodeps" not in myopts:
+			print "Calculating dependencies  ",
+		mydepgraph = depgraph(settings, trees,
+			myopts, myparams, spinner)
+		if "--quiet" not in myopts and "--nodeps" not in myopts:
+			print "\b\b... done!"
+	else:
+		if ("--resume" in myopts):
+			print darkgreen("emerge: It seems we have nothing to resume...")
+			sys.exit(0)
+
+		myparams = create_depgraph_params(myopts, myaction)
+		if myaction in ["system","world"]:
+			if "--quiet" not in myopts and "--nodeps" not in myopts:
+				print "Calculating",myaction,"dependencies  ",
+				sys.stdout.flush()
+			mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
+			if not mydepgraph.xcreate(myaction):
+				print "!!! Depgraph creation failed."
+				sys.exit(1)
+			if "--quiet" not in myopts and "--nodeps" not in myopts:
+				print "\b\b... done!"
+		else:
+			if "--quiet" not in myopts and "--nodeps" not in myopts:
+				print "Calculating dependencies  ",
+				sys.stdout.flush()
+			mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
+			try:
+				retval, favorites = mydepgraph.select_files(myfiles)
+			except portage_exception.PackageNotFound, e:
+				portage.writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
+				sys.exit(1)
+			if not retval:
+				sys.exit(1)
+			if "--quiet" not in myopts and "--nodeps" not in myopts:
+				print "\b\b... done!"
+
+			if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
+				sys.stderr.write(red("The following binaries are not available for merging...\n"))
+
+		if mydepgraph.missingbins:
+			for x in mydepgraph.missingbins:
+				sys.stderr.write("   "+str(x)+"\n")
+			sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n")
+			sys.exit(1)
+
+	if "--pretend" not in myopts and \
+		("--ask" in myopts or "--tree" in myopts or \
+		"--verbose" in myopts) and \
+		not ("--quiet" in myopts and "--ask" not in myopts):
+		if "--resume" in myopts:
+			validate_merge_list(trees, mtimedb["resume"]["mergelist"])
+			mymergelist = mtimedb["resume"]["mergelist"]
+			if "--skipfirst" in myopts:
+				mymergelist = mymergelist[1:]
+			if len(mymergelist) == 0:
+				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
+				sys.exit(0)
+			mydepgraph.display(mymergelist)
+			prompt="Would you like to resume merging these packages?"
+		else:
+			mydepgraph.display(
+				mydepgraph.altlist(reversed=("--tree" in myopts)))
+			mergecount=0
+			for x in mydepgraph.altlist():
+				if x[0] != "blocks" and x[3] != "nomerge":
+					mergecount+=1
+				#check for blocking dependencies
+				if x[0]=="blocks" and "--fetchonly" not in myopts and "--fetch-all-uri" not in myopts:
+					print "\n!!! Error: The above package list contains packages which cannot be installed"
+					print   "!!!        at the same time on the same system."
+					if "--quiet" not in myopts:
+						show_blocker_docs_link()
+					sys.exit(1)
+			if mergecount==0:
+				if "--noreplace" in myopts and favorites:
+					print
+					for x in favorites:
+						print " %s %s" % (good("*"), x)
+					prompt="Would you like to add these packages to your world favorites?"
+				elif settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
+					prompt="Nothing to merge; would you like to auto-clean packages?"
+				else:
+					print
+					print "Nothing to merge; quitting."
+					print
+					sys.exit(0)
+			elif "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
+				prompt="Would you like to fetch the source files for these packages?"
+			else:
+				prompt="Would you like to merge these packages?"
+		print
+		if "--ask" in myopts and userquery(prompt) == "No":
+			print
+			print "Quitting."
+			print
+			sys.exit(0)
+		# Don't ask again (e.g. when auto-cleaning packages after merge)
+		myopts.pop("--ask", None)
+
+	if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
+		if ("--resume" in myopts):
+			validate_merge_list(trees, mtimedb["resume"]["mergelist"])
+			mymergelist = mtimedb["resume"]["mergelist"]
+			if "--skipfirst" in myopts:
+				mymergelist = mymergelist[1:]
+			if len(mymergelist) == 0:
+				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
+				sys.exit(0)
+			mydepgraph.display(mymergelist)
+		else:
+			mydepgraph.display(
+				mydepgraph.altlist(reversed=("--tree" in myopts)))
+	else:
+		if ("--buildpkgonly" in myopts):
+			if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
+				print "\n!!! --buildpkgonly requires all dependencies to be merged."
+				print "!!! Cannot merge requested packages. Merge deps and try again.\n"
+				sys.exit(1)
+
+		if ("--resume" in myopts):
+			favorites=mtimedb["resume"]["favorites"]
+			mergetask = MergeTask(settings, trees, myopts)
+			if "--fetchonly" in myopts:
+				""" parallel-fetch uses --resume --fetchonly and we don't want
+				it to write the mtimedb"""
+				mtimedb.filename = None
+				time.sleep(3) # allow the parent to have first fetch
+			del mydepgraph
+			retval = mergetask.merge(
+				mtimedb["resume"]["mergelist"], favorites, mtimedb)
+			if retval != os.EX_OK:
+				sys.exit(retval)
+		else:
+			if "resume" in mtimedb and \
+			"mergelist" in mtimedb["resume"] and \
+			len(mtimedb["resume"]["mergelist"]) > 1:
+				mtimedb["resume_backup"] = mtimedb["resume"]
+				del mtimedb["resume"]
+				mtimedb.commit()
+			mtimedb["resume"]={}
+			# XXX: Stored as a list for backward compatibility.
+			mtimedb["resume"]["myopts"] = \
+				[k for k in myopts if myopts[k] is True]
+			mtimedb["resume"]["favorites"]=favorites
+			if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
+				for pkgline in mydepgraph.altlist():
+					if pkgline[0]=="ebuild" and pkgline[3]=="merge":
+						y = trees[pkgline[1]]["porttree"].dbapi.findname(pkgline[2])
+						tmpsettings = portage.config(clone=settings)
+						edebug = 0
+						if settings.get("PORTAGE_DEBUG", "") == "1":
+							edebug = 1
+						retval = portage.doebuild(
+							y, "digest", settings["ROOT"], tmpsettings, edebug,
+							("--pretend" in myopts),
+							mydbapi=trees[pkgline[1]]["porttree"].dbapi,
+							tree="porttree")
+			if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
+				pkglist = []
+				for pkg in mydepgraph.altlist():
+					if pkg[0] != "blocks":
+						pkglist.append(pkg)
+			else:
+				pkglist = mydepgraph.altlist()
+			del mydepgraph
+			mergetask = MergeTask(settings, trees, myopts)
+			retval = mergetask.merge(pkglist, favorites, mtimedb)
+			if retval != os.EX_OK:
+				sys.exit(retval)
+
+		if mtimedb.has_key("resume"):
+			del mtimedb["resume"]
+		if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
+			portage.writemsg_stdout(">>> Auto-cleaning packages...\n")
+			vartree = trees[settings["ROOT"]]["vartree"]
+			unmerge(settings, myopts, vartree, "clean", ["world"],
+				ldpath_mtimes, autoclean=1)
+		else:
+			portage.writemsg_stdout(colorize("WARN", "WARNING:")
+				+ " AUTOCLEAN is disabled.  This can cause serious"
+				+ " problems due to overlapping packages.\n")
+
+def multiple_actions(action1, action2):
+	sys.stderr.write("\n!!! Multiple actions requested... Please choose one only.\n")
+	sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2))
+	sys.exit(1)
+
+def parse_opts(tmpcmdline, silent=False):
+	myaction=None
+	myopts = {}
+	myfiles=[]
+
+	global actions, options, shortmapping
+
+	longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
+	argument_options = {
+		"--config-root": {
+			"help":"specify the location for portage configuration files",
+			"action":"store"
+		},
+		"--color": {
+			"help":"enable or disable color output",
+			"type":"choice",
+			"choices":("y", "n")
+		},
+		"--with-bdeps": {
+			"help":"include unnecessary build time dependencies",
+			"type":"choice",
+			"choices":("y", "n")
+		}
+	}
+
+	from optparse import OptionParser
+	parser = OptionParser()
+	if parser.has_option("--help"):
+		parser.remove_option("--help")
+
+	for action_opt in actions:
+		parser.add_option("--" + action_opt, action="store_true",
+			dest=action_opt.replace("-", "_"), default=False)
+	for myopt in options:
+		parser.add_option(myopt, action="store_true",
+			dest=myopt.lstrip("--").replace("-", "_"), default=False)
+	for shortopt, longopt in shortmapping.iteritems():
+		parser.add_option("-" + shortopt, action="store_true",
+			dest=longopt.lstrip("--").replace("-", "_"), default=False)
+	for myalias, myopt in longopt_aliases.iteritems():
+		parser.add_option(myalias, action="store_true",
+			dest=myopt.lstrip("--").replace("-", "_"), default=False)
+
+	for myopt, kwargs in argument_options.iteritems():
+		parser.add_option(myopt,
+			dest=myopt.lstrip("--").replace("-", "_"), **kwargs)
+
+	myoptions, myargs = parser.parse_args(args=tmpcmdline)
+
+	for myopt in options:
+		v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
+		if v:
+			myopts[myopt] = True
+
+	for myopt in argument_options:
+		v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
+		if v is not None:
+			myopts[myopt] = v
+
+	for action_opt in actions:
+		v = getattr(myoptions, action_opt.replace("-", "_"))
+		if v:
+			if myaction:
+				multiple_actions(myaction, action_opt)
+				sys.exit(1)
+			myaction = action_opt
+
+	for x in myargs:
+		if x in actions and myaction != "search":
+			if not silent and x not in ["system", "world"]:
+				print red("*** Deprecated use of action '%s', use '--%s' instead" % (x,x))
+			# special case "search" so people can search for action terms, e.g. emerge -s sync
+			if myaction:
+				multiple_actions(myaction, x)
+				sys.exit(1)
+			myaction = x
+		else:
+			myfiles.append(x)
+
+	if "--nocolor" in myopts:
+		if not silent:
+			sys.stderr.write("*** Deprecated use of '--nocolor', " + \
+				"use '--color=n' instead.\n")
+		del myopts["--nocolor"]
+		myopts["--color"] = "n"
+
+	return myaction, myopts, myfiles
+
+def validate_ebuild_environment(trees):
+	for myroot in trees:
+		mysettings = trees[myroot]["vartree"].settings
+		if not mysettings.get("ARCH", None):
+			print >> sys.stderr, bad("\a!!! ARCH is not set... " + \
+				"Are you missing the '%setc/make.profile' symlink?" % \
+				mysettings["PORTAGE_CONFIGROOT"])
+			print >> sys.stderr, bad("\a!!! Is the symlink correct? " + \
+				"Is your portage tree complete?\n")
+			sys.exit(9)
+		del myroot, mysettings
+
+def load_emerge_config(trees=None):
+	kwargs = {}
+	for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):
+		kwargs[k] = os.environ.get(envvar, None)
+	trees = portage.create_trees(trees=trees, **kwargs)
+
+	settings = trees["/"]["vartree"].settings
+
+	for myroot in trees:
+		if myroot != "/":
+			settings = trees[myroot]["vartree"].settings
+			break
+
+	mtimedbfile = os.path.join("/", portage.CACHE_PATH.lstrip(os.path.sep), "mtimedb")
+	mtimedb = portage.MtimeDB(mtimedbfile)
+	return settings, trees, mtimedb
+
+def adjust_config(myopts, settings):
+	"""Make emerge specific adjustments to the config."""
+
+	# To enhance usability, make some vars case insensitive by forcing them to
+	# lower case.
+	for myvar in ("AUTOCLEAN", "NOCOLOR"):
+		if myvar in settings:
+			settings[myvar] = settings[myvar].lower()
+			settings.backup_changes(myvar)
+	del myvar
+
+	# Kill noauto as it will break merges otherwise.
+	if "noauto" in settings.features:
+		while "noauto" in settings.features:
+			settings.features.remove("noauto")
+		settings["FEATURES"] = " ".join(settings.features)
+		settings.backup_changes("FEATURES")
+
+	CLEAN_DELAY = 5
+	try:
+		CLEAN_DELAY = int(settings.get("CLEAN_DELAY", str(CLEAN_DELAY)))
+	except ValueError, e:
+		portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
+		portage.writemsg("!!! Unable to parse integer: CLEAN_DELAY='%s'\n" % \
+			settings["CLEAN_DELAY"], noiselevel=-1)
+	settings["CLEAN_DELAY"] = str(CLEAN_DELAY)
+	settings.backup_changes("CLEAN_DELAY")
+
+	EMERGE_WARNING_DELAY = 10
+	try:
+		EMERGE_WARNING_DELAY = int(settings.get(
+			"EMERGE_WARNING_DELAY", str(EMERGE_WARNING_DELAY)))
+	except ValueError, e:
+		portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
+		portage.writemsg("!!! Unable to parse integer: EMERGE_WARNING_DELAY='%s'\n" % \
+			settings["EMERGE_WARNING_DELAY"], noiselevel=-1)
+	settings["EMERGE_WARNING_DELAY"] = str(EMERGE_WARNING_DELAY)
+	settings.backup_changes("EMERGE_WARNING_DELAY")
+
+	if "--quiet" in myopts:
+		settings["PORTAGE_QUIET"]="1"
+		settings.backup_changes("PORTAGE_QUIET")
+
+	# Set so that configs will be merged regardless of remembered status
+	if ("--noconfmem" in myopts):
+		settings["NOCONFMEM"]="1"
+		settings.backup_changes("NOCONFMEM")
+
+	# Set various debug markers... They should be merged somehow.
+	PORTAGE_DEBUG = 0
+	try:
+		PORTAGE_DEBUG = int(settings.get("PORTAGE_DEBUG", str(PORTAGE_DEBUG)))
+		if PORTAGE_DEBUG not in (0, 1):
+			portage.writemsg("!!! Invalid value: PORTAGE_DEBUG='%i'\n" % \
+				PORTAGE_DEBUG, noiselevel=-1)
+			portage.writemsg("!!! PORTAGE_DEBUG must be either 0 or 1\n",
+				noiselevel=-1)
+			PORTAGE_DEBUG = 0
+	except ValueError, e:
+		portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
+		portage.writemsg("!!! Unable to parse integer: PORTAGE_DEBUG='%s'\n" %\
+			settings["PORTAGE_DEBUG"], noiselevel=-1)
+		del e
+	if "--debug" in myopts:
+		PORTAGE_DEBUG = 1
+	settings["PORTAGE_DEBUG"] = str(PORTAGE_DEBUG)
+	settings.backup_changes("PORTAGE_DEBUG")
+
+	if settings.get("NOCOLOR") not in ("yes","true"):
+		output.havecolor = 1
+
+	"""The explicit --color < y | n > option overrides the NOCOLOR environment
+	variable and stdout auto-detection."""
+	if "--color" in myopts:
+		if "y" == myopts["--color"]:
+			output.havecolor = 1
+			settings["NOCOLOR"] = "false"
+		else:
+			output.havecolor = 0
+			settings["NOCOLOR"] = "true"
+		settings.backup_changes("NOCOLOR")
+	elif not sys.stdout.isatty() and settings.get("NOCOLOR") != "no":
+		output.havecolor = 0
+		settings["NOCOLOR"] = "true"
+		settings.backup_changes("NOCOLOR")
+
+def emerge_main():
+	# Disable color until we're sure that it should be enabled (after
+	# EMERGE_DEFAULT_OPTS has been parsed).
+	output.havecolor = 0
+	# This first pass is just for options that need to be known as early as
+	# possible, such as --config-root.  They will be parsed again later,
+	# together with EMERGE_DEFAULT_OPTS (which may vary depending on the
+	# the value of --config-root).
+	myaction, myopts, myfiles = parse_opts(sys.argv[1:], silent=True)
+	if "--debug" in myopts:
+		os.environ["PORTAGE_DEBUG"] = "1"
+	if "--config-root" in myopts:
+		os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"]
+
+	# Portage needs to ensure a sane umask for the files it creates.
+	os.umask(022)
+	settings, trees, mtimedb = load_emerge_config()
+	portdb = trees[settings["ROOT"]]["porttree"].dbapi
+
+	try:
+		os.nice(int(settings.get("PORTAGE_NICENESS", "0")))
+	except (OSError, ValueError), e:
+		portage.writemsg("!!! Failed to change nice value to '%s'\n" % \
+			settings["PORTAGE_NICENESS"])
+		portage.writemsg("!!! %s\n" % str(e))
+		del e
+
+	if portage.global_updates(settings, trees, mtimedb["updates"]):
+		mtimedb.commit()
+		# Reload the whole config from scratch.
+		settings, trees, mtimedb = load_emerge_config(trees=trees)
+		portdb = trees[settings["ROOT"]]["porttree"].dbapi
+
+	xterm_titles = "notitles" not in settings.features
+
+	tmpcmdline = []
+	if "--ignore-default-opts" not in sys.argv:
+		tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split())
+	tmpcmdline.extend(sys.argv[1:])
+	myaction, myopts, myfiles = parse_opts(tmpcmdline)
+
+	if "--digest" in myopts:
+		os.environ["FEATURES"] = os.environ.get("FEATURES","") + " digest"
+		# Reload the whole config from scratch so that the portdbapi internal
+		# config is updated with new FEATURES.
+		settings, trees, mtimedb = load_emerge_config(trees=trees)
+		portdb = trees[settings["ROOT"]]["porttree"].dbapi
+
+	for myroot in trees:
+		mysettings =  trees[myroot]["vartree"].settings
+		mysettings.unlock()
+		adjust_config(myopts, mysettings)
+		mysettings.lock()
+		del myroot, mysettings
+
+	spinner = stdout_spinner()
+	if "candy" in settings.features:
+		spinner.update = spinner.update_scroll
+
+	portage.deprecated_profile_check()
+
+	#Freeze the portdbapi for enhanced performance:
+	for myroot in trees:
+		trees[myroot]["porttree"].dbapi.freeze()
+		del myroot
+
+	if "moo" in myfiles:
+		print """
+
+  Larry loves Gentoo (""" + os.uname()[0] + """)
+
+ _______________________
+< Have you mooed today? >
+ -----------------------
+        \   ^__^
+         \  (oo)\_______
+            (__)\       )\/\ 
+                ||----w |
+                ||     ||
+
+"""
+
+	if (myaction in ["world", "system"]) and myfiles:
+		print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both."
+		sys.exit(1)
+
+	for x in myfiles:
+		ext = os.path.splitext(x)[1]
+		if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)):
+			print "emerging by path implies --oneshot... adding --oneshot to options."
+			print colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n")
+			break
+
+	if ("--tree" in myopts) and ("--columns" in myopts):
+		print "emerge: can't specify both of \"--tree\" and \"--columns\"."
+		sys.exit(1)
+
+	if ("--quiet" in myopts):
+		spinner.update = spinner.update_quiet
+		portage_util.noiselimit = -1
+
+	# Always create packages if FEATURES=buildpkg
+	# Imply --buildpkg if --buildpkgonly
+	if ("buildpkg" in settings.features) or ("--buildpkgonly" in myopts):
+		if "--buildpkg" not in myopts:
+			myopts["--buildpkg"] = True
+
+	# Also allow -S to invoke search action (-sS)
+	if ("--searchdesc" in myopts):
+		if myaction and myaction != "search":
+			myfiles.append(myaction)
+		if "--search" not in myopts:
+			myopts["--search"] = True
+		myaction = "search"
+
+	# Always try and fetch binary packages if FEATURES=getbinpkg
+	if ("getbinpkg" in settings.features):
+		myopts["--getbinpkg"] = True
+
+	if "--skipfirst" in myopts and "--resume" not in myopts:
+		myopts["--resume"] = True
+
+	if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
+		myopts["--usepkgonly"] = True
+
+	if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
+		myopts["--getbinpkg"] = True
+
+	if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
+		myopts["--usepkg"] = True
+
+	# Also allow -K to apply --usepkg/-k
+	if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
+		myopts["--usepkg"] = True
+
+	# Also allow -l to apply --pretend/-p, but if already in --ask mode
+	if ("--changelog" in myopts) and not (("--pretend" in myopts) or ("--ask" in myopts)):
+		print ">>> --changelog implies --pretend... adding --pretend to options."
+		myopts["--pretend"] = True
+
+	# Allow -p to remove --ask
+	if ("--pretend" in myopts) and ("--ask" in myopts):
+		print ">>> --pretend disables --ask... removing --ask from options."
+		del myopts["--ask"]
+
+	# forbid --ask when not in a terminal
+	# note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway.
+	if ("--ask" in myopts) and (not sys.stdin.isatty()):
+		portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n",
+			noiselevel=-1)
+		sys.exit(1)
+
+	if settings.get("PORTAGE_DEBUG", "") == "1":
+		spinner.update = spinner.update_quiet
+		portage.debug=1
+		if "python-trace" in settings.features:
+			import portage_debug
+			portage_debug.set_trace(True)
+
+	if ("--resume" in myopts):
+		if "--tree" in myopts:
+			print "* --tree is currently broken with --resume. Disabling..."
+			del myopts["--tree"]
+
+	if not ("--quiet" in myopts):
+		if not sys.stdout.isatty() or ("--nospinner" in myopts):
+			spinner.update = spinner.update_basic
+
+	if "--version" in myopts:
+		print getportageversion(settings["PORTDIR"], settings["ROOT"],
+			settings.profile_path, settings["CHOST"],
+			trees[settings["ROOT"]]["vartree"].dbapi)
+		sys.exit(0)
+	elif "--help" in myopts:
+		emergehelp.help(myaction, myopts, output.havecolor)
+		sys.exit(0)
+
+	if portage.wheelgid == portage.portage_gid:
+		print "emerge: wheel group use is being deprecated. Please update group and passwd to"
+		print "        include the portage user as noted above, and then use group portage."
+
+	if "--debug" in myopts:
+		print "myaction", myaction
+		print "myopts", myopts
+
+	if not myaction and not myfiles and "--resume" not in myopts:
+		emergehelp.help(myaction, myopts, output.havecolor)
+		sys.exit(1)
+
+	# check if root user is the current user for the actions where emerge needs this
+	if portage.secpass < 2:
+		# We've already allowed "--version" and "--help" above.
+		if "--pretend" not in myopts and \
+		myaction not in ("search","info"):
+			need_superuser = not \
+				("--fetchonly" in myopts or \
+				"--fetch-all-uri" in myopts or \
+				myaction in ("metadata", "regen"))
+			if portage.secpass < 1 or \
+				need_superuser:
+				if need_superuser:
+					access_desc = "superuser"
+				else:
+					access_desc = "portage group"
+				# Always show portage_group_warning() when only portage group
+				# access is required but the user is not in the portage group.
+				from portage_data import portage_group_warning
+				if "--ask" in myopts:
+					myopts["--pretend"] = True
+					del myopts["--ask"]
+					print ("%s access would be required... " + \
+						"adding --pretend to options.\n") % access_desc
+					if portage.secpass < 1 and not need_superuser:
+						portage_group_warning()
+				else:
+					sys.stderr.write(("emerge: %s access would be " + \
+						"required.\n\n") % access_desc)
+					if portage.secpass < 1 and not need_superuser:
+						portage_group_warning()
+					return 1
+
+	disable_emergelog = False
+	for x in ("--pretend", "--fetchonly", "--fetch-all-uri"):
+		if x in myopts:
+			disable_emergelog = True
+			break
+	if myaction in ("search", "info"):
+		disable_emergelog = True
+	if disable_emergelog:
+		""" Disable emergelog for everything except build or unmerge
+		operations.  This helps minimize parallel emerge.log entries that can
+		confuse log parsers.  We especially want it disabled during
+		parallel-fetch, which uses --resume --fetchonly."""
+		global emergelog
+		def emergelog(*pargs, **kargs):
+			pass
+
+	if not "--pretend" in myopts:
+		emergelog(xterm_titles, "Started emerge on: "+\
+			time.strftime("%b %d, %Y %H:%M:%S", time.localtime()))
+		myelogstr=""
+		if myopts:
+			myelogstr=" ".join(myopts)
+		if myaction:
+			myelogstr+=" "+myaction
+		if myfiles:
+			myelogstr+=" "+" ".join(myfiles)
+		emergelog(xterm_titles, " *** emerge " + myelogstr)
+
+	def emergeexitsig(signum, frame):
+		signal.signal(signal.SIGINT, signal.SIG_IGN)
+		signal.signal(signal.SIGTERM, signal.SIG_IGN)
+		portage_util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum})
+		sys.exit(100+signum)
+	signal.signal(signal.SIGINT, emergeexitsig)
+	signal.signal(signal.SIGTERM, emergeexitsig)
+
+	def emergeexit():
+		"""This gets out final log message in before we quit."""
+		if "--pretend" not in myopts:
+			emergelog(xterm_titles, " *** terminating.")
+		if "notitles" not in settings.features:
+			xtermTitleReset()
+	portage.atexit_register(emergeexit)
+
+	if myaction in ("config", "metadata", "regen", "sync"):
+		if "--pretend" in myopts:
+			sys.stderr.write(("emerge: The '%s' action does " + \
+				"not support '--pretend'.\n") % myaction)
+			return 1
+	if "sync" == myaction:
+		action_sync(settings, trees, mtimedb, myopts, myaction)
+	elif "metadata" == myaction:
+		action_metadata(settings, portdb, myopts)
+	elif myaction=="regen":
+		validate_ebuild_environment(trees)
+		action_regen(settings, portdb)
+	# HELP action
+	elif "config"==myaction:
+		validate_ebuild_environment(trees)
+		action_config(settings, trees, myopts, myfiles)
+	
+	# INFO action
+	elif "info"==myaction:
+		action_info(settings, trees, myopts, myfiles)
+
+	# SEARCH action
+	elif "search"==myaction:
+		validate_ebuild_environment(trees)
+		action_search(settings, portdb, trees["/"]["vartree"],
+			myopts, myfiles, spinner)
+	elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction:
+		validate_ebuild_environment(trees)
+		vartree = trees[settings["ROOT"]]["vartree"]
+		if 1 == unmerge(settings, myopts, vartree, myaction, myfiles,
+			mtimedb["ldpath"]):
+			if "--pretend" not in myopts:
+				post_emerge(settings, mtimedb, 0)
+
+	elif "depclean"==myaction:
+		validate_ebuild_environment(trees)
+		action_depclean(settings, trees, mtimedb["ldpath"],
+			myopts, spinner)
+		if "--pretend" not in myopts:
+			post_emerge(settings, mtimedb, 0)
+	# "update", "system", or just process files:
+	else:
+		validate_ebuild_environment(trees)
+		action_build(settings, trees, mtimedb,
+			myopts, myaction, myfiles, spinner)
+		if "--pretend" not in myopts:
+			post_emerge(settings, mtimedb, 0)
+
+if __name__ == "__main__":
+	retval = emerge_main()
+	sys.exit(retval)
Index: /vendor/portage/current/bin/emerge-webrsync
===================================================================
--- /vendor/portage/current/bin/emerge-webrsync	(revision 3419)
+++ /vendor/portage/current/bin/emerge-webrsync	(revision 3419)
@@ -0,0 +1,165 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: emerge-webrsync 5154 2006-12-02 08:07:37Z zmedico $
+# Author: Karl Trygve Kalleberg <karltk@gentoo.org>
+# Rewritten from the old, Perl-based emerge-webrsync script
+
+type portageq > /dev/null || exit $?
+eval $(portageq envvar -v FEATURES FETCHCOMMAND GENTOO_MIRRORS \
+	PORTAGE_BIN_PATH PORTAGE_INST_UID PORTAGE_INST_GID PORTAGE_NICENESS \
+	GENTOO_MIRRORS PORTAGE_INST_UID PORTAGE_INST_GID PORTAGE_NICENESS \
+	PORTAGE_TMPDIR PORTDIR)
+DISTDIR="${PORTAGE_TMPDIR}/emerge-webrsync"
+
+# If PORTAGE_NICENESS is overriden via the env then it will
+# still pass through the portageq call and override properly.
+if [ -n "${PORTAGE_NICENESS}" ]; then
+	renice $PORTAGE_NICENESS $$ > /dev/null
+fi
+
+source "${PORTAGE_BIN_PATH}"/isolated-functions.sh || exit 1
+
+if [ ! -d $DISTDIR ] ; then
+	mkdir -p $DISTDIR
+fi
+
+cd "$DISTDIR"
+
+found=0
+if [ "$1" == "-v" ] ; then
+	wgetops=
+else	
+	#this sucks.  probably better to do 1> /dev/null
+	#that said, waiting on the refactoring.
+	if [ "${FETCHCOMMAND/wget}" != "${FETCHCOMMAND}" ]; then
+		wgetops="-q"
+	elif [ "${FETCHCOMMAND/curl}" != "${FETCHCOMMAND}" ]; then
+		wgetops="-s -f"
+	fi
+fi
+
+if type -P md5sum > /dev/null; then
+	md5_com='md5sum -c "${FILE}.md5sum"'
+elif type -P md5 > /dev/null; then
+	md5_com='[ "$(md5 -q ${FILE})" == "$(cut -d \  -f 1 ${FILE}.md5sum)" ]'
+else
+	echo "warning, unable to do md5 verification of the snapshot!"
+	echo "no suitable md5/md5sum binary was found!"
+	md5_com='true'
+fi
+
+sync_local() {
+	echo Syncing local tree...
+	if type -P tarsync &> /dev/null; then
+		# tarsync doesn't take numeric uid/gid so we need to convert them.
+		local inst_user="$(python -c "import pwd; print pwd.getpwuid(int('${PORTAGE_INST_UID:-0}'))[0]")"
+		local inst_group="$(python -c "import grp; print grp.getgrgid(int('${PORTAGE_INST_GID:-0}'))[0]")"
+		if ! tarsync "${FILE}" "${PORTDIR}" -v -s 1 -o ${inst_user} -g ${inst_group} -e /distfiles -e /packages -e /local; then
+			echo "tarsync failed; tarball is corrupt?"
+			exit 1;
+		fi
+		rm "${FILE}"
+	else
+		if ! tar jxf $FILE; then
+			echo "Tar failed to extract the image. Please review the output."
+			echo "Executed command: tar jxf $FILE"
+			exit 1
+		fi
+		rm -f $FILE
+		# Make sure user and group file ownership is ${PORTAGE_INST_UID}:${PORTAGE_INST_GID}
+		chown -R ${PORTAGE_INST_UID:-0}:${PORTAGE_INST_GID:-0} portage
+		cd portage
+		rsync -av --progress --stats --delete --delete-after \
+		--exclude='/distfiles' --exclude='/packages' \
+		--exclude='/local' . ${PORTDIR%%/}
+		cd ..
+		echo "cleaning up"
+		rm -rf portage
+	fi
+	if hasq metadata-transfer ${FEATURES} ; then
+		echo "transferring metadata/cache"
+		emerge --metadata
+	fi
+	[ -x /etc/portage/bin/post_sync ] && /etc/portage/bin/post_sync
+}
+
+echo "Fetching most recent snapshot"
+
+declare -i attempts=0
+while (( $attempts <  40 )) ; do
+	attempts=$(( attempts + 1 ))
+
+	# The snapshot for a given day is generated at 01:45 UTC on the following
+	# day, so the current day's snapshot (going by UTC time) hasn't been
+	# generated yet.  Therefore, always start by looking for the previous day's
+	# snapshot (for attempts=1, subtract 1 day from the current UTC time).
+	daysbefore=$(expr $(date -u +"%s") - 86400 \* ${attempts})
+	DATE_ARGS="-d @${daysbefore}"
+	# ${USERLAND} is unreliable since the portage tree might be empty, so test
+	# success of the -r option to distinguish between gnu and bsd date.
+	date -r ${daysbefore} >&/dev/null && DATE_ARGS="-r ${daysbefore}"
+	day=$(date ${DATE_ARGS} -u +"%d")
+	month=$(date ${DATE_ARGS} -u +"%m")
+	year=$(date ${DATE_ARGS} -u +"%Y")
+
+	FILE_ORIG="portage-${year}${month}${day}.tar.bz2"
+
+	echo "Attempting to fetch file dated: ${year}${month}${day}"
+		
+	got_md5=0
+
+	if [  ! -e "${FILE_ORIG}.md5sum" ]; then
+		FILE="${FILE_ORIG}.md5sum"
+		for i in $GENTOO_MIRRORS ; do 
+			URI="${i}/snapshots/${FILE}"
+			if (eval "$FETCHCOMMAND $wgetops") && [ -s "${FILE}" ]; then
+				got_md5=1
+				break
+			fi
+		done
+	else
+		got_md5=1
+	fi
+	FILE="${FILE_ORIG}"
+
+	if (($got_md5 == 0 )); then
+		echo " --- No md5sum present on the mirror. (Not yet available.)"
+		continue
+	elif [ -s "${FILE}" ]; then
+		if eval "$md5_com"; then
+			echo " === snapshot $FILE is correct, using it"
+			sync_local
+			echo
+			echo " === Snapshot has been sync'd"
+			echo
+			exit 0
+		else
+			rm $FILE
+		fi
+	fi
+	
+	for i in $GENTOO_MIRRORS ; do
+		URI="${i}/snapshots/$FILE"
+		rm -f "$FILE"
+		if (eval "$FETCHCOMMAND $wgetops") && [ -s "$FILE" ]; then
+			if ! eval "$md5_com"; then
+				echo "md5 failed on $FILE"
+				rm ${FILE}
+				continue
+			else
+				sync_local
+				echo
+				echo " *** Completed websync, please now perform a normal rsync if possible."
+				echo "     Update is current as of the of YYYYMMDD: ${year}${month}${day}"
+				echo
+				exit 0
+			fi
+		fi
+
+	done
+done
+
+rm -rf portage
+
+exit 1
Index: /vendor/portage/current/bin/env-update
===================================================================
--- /vendor/portage/current/bin/env-update	(revision 3419)
+++ /vendor/portage/current/bin/env-update	(revision 3419)
@@ -0,0 +1,39 @@
+#!/usr/bin/python -O
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: env-update 4884 2006-10-31 04:23:06Z zmedico $
+
+import os, sys, errno
+
+def usage(status):
+	print "Usage: env-update [--no-ldconfig]"
+	print ""
+	print "See the env-update(1) man page for more info"
+	sys.exit(status)
+
+if "-h" in sys.argv or "--help" in sys.argv:
+	usage(0)
+
+makelinks=1
+if "--no-ldconfig" in sys.argv:
+	makelinks=0
+	sys.argv.pop(sys.argv.index("--no-ldconfig"))
+
+if len(sys.argv) > 1:
+	print "!!! Invalid command line options!\n"
+	usage(1)
+
+try:
+	import portage
+except ImportError:
+	from os import path as osp
+	sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
+	import portage
+try:
+	portage.env_update(makelinks)
+except IOError, e:
+	if e.errno == errno.EACCES:
+		print "env-update: Need superuser access"
+		sys.exit(1)
+	else:
+		raise
Index: /vendor/portage/current/bin/env-update.orig
===================================================================
--- /vendor/portage/current/bin/env-update.orig	(revision 3419)
+++ /vendor/portage/current/bin/env-update.orig	(revision 3419)
@@ -0,0 +1,31 @@
+#!/usr/bin/python -O
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: env-update 4884 2006-10-31 04:23:06Z zmedico $
+
+import os,sys
+
+def usage(status):
+	print "Usage: env-update [--no-ldconfig]"
+	print ""
+	print "See the env-update(1) man page for more info"
+	sys.exit(status)
+
+if "-h" in sys.argv or "--help" in sys.argv:
+	usage(0)
+
+makelinks=1
+if "--no-ldconfig" in sys.argv:
+	makelinks=0
+	sys.argv.pop(sys.argv.index("--no-ldconfig"))
+
+if len(sys.argv) > 1:
+	print "!!! Invalid command line options!\n"
+	usage(1)
+
+try:
+	import portage
+except ImportError:
+	sys.path.insert(0, "/usr/lib/portage/pym")
+	import portage
+portage.env_update(makelinks)
Index: /vendor/portage/current/bin/env-update.sh
===================================================================
--- /vendor/portage/current/bin/env-update.sh	(revision 3419)
+++ /vendor/portage/current/bin/env-update.sh	(revision 3419)
@@ -0,0 +1,219 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: env-update.sh 3483 2006-06-10 21:40:40Z genone $
+
+############################################
+############################################
+# ENVIRONMENT SETUP
+############################################
+
+if [[ ${EUID} -ne 0 ]] ; then
+	echo "$0: must be root."
+	exit 1
+fi
+
+# Make sure our environment is sane
+if [[ ! -z "${MAKELINKS}" ]] ; then
+	export MAKELINKS=0
+else
+	export MAKELINKS=1
+fi
+export ROOT="${ROOT:=/}"
+[[ ${ROOT} == */ ]] || export ROOT="${ROOT}/"
+
+export ENVDIR="${ROOT}etc/env.d"
+mkdir -p ${ENVDIR}
+chmod 755 ${ENVDIR}
+specials="
+	KDEDIRS PATH CLASSPATH LDPATH MANPATH INFODIR INFOPATH ROOTPATH
+	CONFIG_PROTECT CONFIG_PROTECT_MASK PRELINK_PATH PYTHONPATH
+	PRELINK_PATH_MASK ADA_INCLUDE_PATH ADA_OBJECTS_PATH"
+colon_separated="
+	ADA_INCLUDE_PATH ADA_OBJECTS_PATH LDPATH PATH MANPATH ROOTPATH
+	PRELINK_PATH PRELINK_PATH_MASK PYTHON_PATH"
+
+export LDSOCONF="${ROOT}etc/ld.so.conf"
+
+export PRELINKCONF="${ROOT}etc/prelink.conf"
+defaultprelinkpaths=":/bin:/sbin:/usr/bin:/usr/sbin:/lib:/usr/lib"
+
+export PROFILEENV="${ROOT}etc/profile.env"
+export CSHENV="${ROOT}etc/csh.env"
+
+# make sure we aren't tricked with previous 'my_envd_' variables
+unset $(set | grep '^my_envd_' | cut -d= -f1)
+
+############################################
+############################################
+# ENV.D PARSING
+############################################
+
+do_has() {
+	local x
+	local me="$1"
+	shift
+
+	for x in "$@" ; do
+		[[ ${x} == ${me} ]] && return 0
+	done
+	return 1
+}
+has() {
+	local ret
+	local ifs="${IFS}"
+	unset IFS
+	do_has $1 ${!2}
+	ret=$?
+	export IFS="${ifs}"
+	return ${ret}
+}
+is_special() {
+	has $1 specials
+}
+is_colon_separated() {
+	has $1 colon_separated
+}
+
+for envd in $(ls ${ENVDIR} | sort) ; do
+	# make sure file is a vaild env'd entry and not a backup file
+	num="${envd:0:2}"
+	if [[ ! -z ${num//[0-9]} ]] ; then
+		continue
+	elif [[ ${envd} == *~ || ${envd} == *.bak ]] ; then
+		continue
+	fi
+
+	# use bash to make sure the file is valid
+	envd="${ENVDIR}/${envd}"
+	if ! (source "${envd}") ; then
+		echo "!!! Error parsing ${envd}!"
+		exit 1
+	fi
+
+	# parse env.d entries
+	cnfvars="$(grep '^[[:alpha:]_][[:alnum:]_]*=' "${envd}")"
+	export IFS=$'\n'
+	for cnfv in ${cnfvars} ; do
+		var="${cnfv/=*}"
+		val="${cnfv:${#var}+1}"
+		if [ "${val:0:1}" == "\"" ] ; then
+			val="${val:1:${#val}-2}"
+		fi
+		myvar="my_envd_${var}"
+		if is_special ${var} ; then
+			if [[ ! -z "${!myvar}" ]] ; then
+				if is_colon_separated ${var} ; then
+					sep=":"
+				else
+					sep=" "
+				fi
+			else
+				sep=""
+			fi
+			export ${myvar}="${!myvar}${sep}${val}"
+		else
+			export ${myvar}="${val}"
+		fi
+	done
+	unset IFS
+done
+
+############################################
+############################################
+# LD.SO.CONF HANDLING
+############################################
+
+# create a : sep list from ld.so.conf
+export OLD_LDPATH=""
+if [ -s "${LDSOCONF}" ] ; then
+	while read line ; do
+		if [[ "${line:0:1}" == "#" ]] ; then
+			continue
+		fi
+		export OLD_LDPATH="${OLD_LDPATH}:${line}"
+	done < ${LDSOCONF}
+	export OLD_LDPATH="${OLD_LDPATH:1}"
+fi
+
+# has the ldpath changed ?  if so, recreate
+if [[ "${OLD_LDPATH}" != "${my_envd_LDPATH}" ]] ; then
+	cat << EOF > ${LDSOCONF}
+# ld.so.conf autogenerated by env-update; make all changes to
+# contents of /etc/env.d directory
+${my_envd_LDPATH//:/
+}
+EOF
+fi
+
+############################################
+############################################
+# HANDLE PRELINK PATHS
+############################################
+
+if prelink --version >& /dev/null ; then
+	# we assume LDPATH and PATH aren't empty ... if they were, we got other problems
+	envdprelinkcheckpaths="${my_envd_LDPATH}:${my_envd_PATH}"
+	if [[ ! -z "${my_envd_PRELINK_PATH}" ]] ; then
+		envdprelinkcheckpaths="${envdprelinkcheckpaths}:${my_envd_PRELINK_PATH}"
+	fi
+
+	if [[ ! -z "${my_envd_PRELINK_PATH_MASK}" ]] ; then
+		export prelink_mask=":${PRELINK_PATH_MASK}:"
+		envdprelinkpaths=""
+		export IFS=":"
+		for dir in ${envdprelinkcheckpaths} ; do
+			if [[ ${dir:0-1} == / ]] ; then
+				noslashdir="${dir:0:${#dir}-1}"
+			else
+				dir="${dir}/"
+				noslashdir="${dir}"
+			fi
+			if [[ ${prelink_mask/:${dir}:/} == ${prelink_mask} \
+				&& ${prelink_mask/:${noslashdir}:/} == ${prelink_mask} ]] ; then
+				envdprelinkpaths="${envdprelinkpaths}:${dir}"
+			fi
+		done
+		unset IFS
+	else
+		envdprelinkpaths=":${envdprelinkcheckpaths}"
+	fi
+
+	cat << EOF > ${PRELINKCONF}
+# prelink.conf autogenerated by env-update; make all changes to
+# contents of /etc/env.d directory
+${defaultprelinkpaths//:/
+-l }
+${envdprelinkpaths//:/
+-h }
+EOF
+fi
+unset my_envd_LDPATH
+
+############################################
+############################################
+# RUN EXTERNAL PROGRAMS NOW
+############################################
+
+echo ">>> Regenerating ${ROOT}etc/ld.so.cache..."
+if [[ ${MAKELINKS} -eq 0 ]] ; then
+	(cd / ; /sbin/ldconfig -X -r ${ROOT} >& /dev/null)
+else
+	(cd / ; /sbin/ldconfig -r ${ROOT} >& /dev/null)
+fi
+
+cat << EOF > ${PROFILEENV}
+# THIS FILE IS AUTOMATICALLY GENERATED BY env-update.
+# DO NOT EDIT THIS FILE. CHANGES TO STARTUP PROFILES
+# GO INTO /etc/profile NOT /etc/profile.env
+
+$(set | grep '^my_envd_' | sed -e 's:^my_envd_:export :')
+EOF
+
+cat << EOF > ${CSHENV}
+# THIS FILE IS AUTOMATICALLY GENERATED BY env-update.
+# DO NOT EDIT THIS FILE. CHANGES TO STARTUP PROFILES
+# GO INTO /etc/csh.cshrc NOT /etc/csh.env
+
+$(set | grep '^my_envd_' | sed -e 's:^my_envd_\([[:alpha:]_][[:alnum:]_]*\)=:setenv \1 :')
+EOF
Index: /vendor/portage/current/bin/etc-update
===================================================================
--- /vendor/portage/current/bin/etc-update	(revision 3419)
+++ /vendor/portage/current/bin/etc-update	(revision 3419)
@@ -0,0 +1,499 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: etc-update 5135 2006-11-26 14:06:38Z zmedico $
+
+# Author Brandon Low <lostlogic@gentoo.org>
+#
+# Previous version (from which I've borrowed a few bits) by:
+# Jochem Kossen <j.kossen@home.nl>
+# Leo Lipelis <aeoo@gentoo.org>
+# Karl Trygve Kalleberg <karltk@gentoo.org>
+
+if type -P gsed >/dev/null ; then
+	function sed() { gsed "$@"; }
+fi
+
+function get_config() {
+	item=$1
+
+	# First strip off comment lines, then grab the configuration
+	# item. If there's more than one of the same configuration item,
+	# then allow the last setting to take precedence.
+	local result
+	result=$(cut -d'#' -f1-1 ${PORTAGE_CONFIGROOT}etc/etc-update.conf | \
+		sed -ne "s/^ *$item *= *\([\"']\{0,1\}\)\(.*\)\1/\2/p" |sed -e '$p;d')
+	eval echo $result
+}
+
+function scan() {
+
+	echo "Scanning Configuration files..."
+	rm -rf ${TMP}/files > /dev/null 2>&1
+	mkdir ${TMP}/files || die "Failed mkdir command!" 1
+	count=0
+	input=0
+	local find_opts
+	local my_basename
+
+	# Sanity check to make sure diff exists and works
+	if ! diff -v &>/dev/null ; then
+		echo "ERROR: 'diff' does not seem to work, aborting"
+		exit 1
+	fi
+
+	for path in ${CONFIG_PROTECT} ; do
+		path="${ROOT}${path}"
+		find_opts="-iname ._cfg????_*"
+		if [ ! -d "${path}" ]; then
+			[ ! -f "${path}" ] && continue
+			my_basename="${path##*/}"
+			path="${path%/*}"
+			find_opts="-maxdepth 1 -iname ._cfg????_${my_basename}"
+		fi
+
+		ofile=""
+		# The below set -f turns off file name globbing in the ${find_opts} expansion.
+		for file in $(set -f; find ${path}/ ${find_opts} ! -iname '.*~' ! -iname '.*.bak' |
+			   sed -e "s:\(^.*/\)\(\._cfg[0-9]*_\)\(.*$\):\1\2\3\%\2\%\3:" |
+			   sort -t'%' -k3 -k2 | LANG=POSIX LC_ALL=POSIX cut -f1 -d'%'); do
+			rpath=$(echo "${file/\/\///}" | sed -e "s:/[^/]*$::")
+			rfile=$(echo "${file/\/\///}" | sed -e "s:^.*/::")
+			for mpath in ${CONFIG_PROTECT_MASK}; do
+				mpath="${ROOT}${mpath}"
+				mpath=$(echo "${mpath/\/\///}")
+				if [[ "${rpath}" == "${mpath}"* ]]; then
+					mv ${rpath}/${rfile} ${rpath}/${rfile:10}
+					break
+				fi
+			done
+			[ ! -f ${file} ] && continue
+
+
+			if [[ "${ofile:10}" != "${rfile:10}" ]] ||
+			   [[ ${opath} != ${rpath} ]]; then
+				MATCHES=0
+				if [[ "${EU_AUTOMERGE}" == "yes" ]]; then
+					if [ ! -e "${rpath}/${rfile}" ] || [ ! -e "${rpath}/${rfile:10}" ]; then
+						MATCHES=0
+					else
+						diff -Bbua ${rpath}/${rfile} ${rpath}/${rfile:10} | egrep '^[+-]' | egrep -v '^[+-][\t ]*#|^--- |^\+\+\+ ' | egrep -qv '^[-+][\t ]*$'
+						MATCHES=$?
+					fi
+				elif [[ -z $(diff -Nua ${rpath}/${rfile} ${rpath}/${rfile:10}|
+							  grep "^[+-][^+-]"|grep -v '# .Header:.*') ]]; then
+					MATCHES=1
+				fi
+				if [[ "${MATCHES}" == "1" ]]; then
+					echo "Automerging trivial changes in: ${rpath}/${rfile:10}"
+					mv ${rpath}/${rfile} ${rpath}/${rfile:10}
+					continue
+				else
+					count=${count}+1
+					echo "${rpath}/${rfile:10}" > ${TMP}/files/${count}
+					echo "${rpath}/${rfile}" >> ${TMP}/files/${count}
+					ofile="${rfile}"
+					opath="${rpath}"
+					continue
+				fi
+			fi
+
+			if [[ -z $(diff -Nua ${rpath}/${rfile} ${rpath}/${ofile}|
+					  grep "^[+-][^+-]"|grep -v '# .Header:.*') ]]; then
+				mv ${rpath}/${rfile} ${rpath}/${ofile}
+				continue
+			else
+				echo "${rpath}/${rfile}" >> ${TMP}/files/${count}
+				ofile="${rfile}"
+				opath="${rpath}"
+			fi
+		done
+	done
+
+}
+
+function sel_file() {
+	local -i isfirst=0
+	until [[ -f ${TMP}/files/${input} ]] || \
+	      [[ ${input} == -1 ]] || \
+	      [[ ${input} == -3 ]]
+	do
+		local numfiles=$(ls ${TMP}/files|wc -l)
+		local numwidth=${#numfiles}
+		for file in $(ls ${TMP}/files|sort -n); do
+			if [[ ${isfirst} == 0 ]] ; then
+				isfirst=${file}
+			fi
+			numshow=$(printf "%${numwidth}i${PAR} " ${file})
+			numupdates=$(( $(wc -l <${TMP}/files/${file}) - 1 ))
+			echo -n "${numshow}"
+			if [[ ${mode} == 0 ]] ; then
+				echo "$(head -n1 ${TMP}/files/${file}) (${numupdates})"
+			else
+				head -n1 ${TMP}/files/${file}
+			fi
+		done > ${TMP}/menuitems
+
+		if [ "${OVERWRITE_ALL}" == "yes" ]; then
+			input=0
+		elif [ "${DELETE_ALL}" == "yes" ]; then
+			input=0
+		else
+			if [[ ${mode} == 0 ]] ; then
+				echo "The following is the list of files which need updating, each
+configuration file is followed by a list of possible replacement files."
+			else
+				local my_title="Please select a file to update"
+			fi
+
+			if [[ ${mode} == 0 ]] ; then
+				cat ${TMP}/menuitems
+				echo    "Please select a file to edit by entering the corresponding number."
+				echo    "              (don't use -3, -5, -7 or -9 if you're unsure what to do)"
+				echo    "              (-1 to exit) (-3 to auto merge all remaining files)"
+				echo    "                           (-5 to auto-merge AND not use 'mv -i')"
+				echo    "                           (-7 to discard all updates)"
+				echo -n "                           (-9 to discard all updates AND not use 'rm -i'): "
+				input=$(read_int)
+			else
+				dialog --title "${title}" --menu "${my_title}" \
+					0 0 0 $(echo -e "-1 Exit\n$(<${TMP}/menuitems)") \
+					2> ${TMP}/input || die "User termination!" 0
+				input=$(<${TMP}/input)
+			fi
+			if [[ ${input} == -9 ]]; then
+				read -p "Are you sure that you want to delete all updates (type YES):" reply
+				if [[ ${reply} != "YES" ]]; then
+					continue
+				else
+					input=-7
+					export rm_opts=""
+				fi
+			fi
+			if [[ ${input} == -7 ]]; then
+				input=0
+				export DELETE_ALL="yes"
+			fi
+			if [[ ${input} == -5 ]] ; then
+				input=-3
+				export mv_opts=""
+			fi
+			if [[ ${input} == -3 ]] ; then
+				input=0
+				export OVERWRITE_ALL="yes"
+			fi
+		fi # -3 automerge
+		if [[ -z ${input} ]] || [[ ${input} == 0 ]] ; then
+			input=${isfirst}
+		fi
+	done
+}
+
+function user_special() {
+	if [ -r ${PORTAGE_CONFIGROOT}etc/etc-update.special ]; then
+		if [ -z "$1" ]; then
+			echo "ERROR: user_special() called without arguments"
+			return 1
+		fi
+		while read pat; do
+			echo ${1} | grep "${pat}" > /dev/null && return 0
+		done < ${PORTAGE_CONFIGROOT}etc/etc-update.special
+	fi
+	return 1
+}
+
+function read_int() {
+	# Read an integer from stdin.  Continously loops until a valid integer is
+	# read.  This is a workaround for odd behavior of bash when an attempt is
+	# made to store a value such as "1y" into an integer-only variable.
+	local my_input
+	while true; do
+		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
+	done
+	echo ${my_input}
+}
+
+function do_file() {
+	echo
+	local -i my_input
+	local -i fcount=0
+	until (( $(wc -l < ${TMP}/files/${input}) < 2 )); do
+		my_input=0
+		if (( $(wc -l < ${TMP}/files/${input}) == 2 )); then
+			my_input=1
+		fi
+		until (( ${my_input} > 0 )) && (( ${my_input} < $(wc -l < ${TMP}/files/${input}) )); do
+			fcount=0
+
+			if [ "${OVERWRITE_ALL}" == "yes" ]; then
+				my_input=0
+			elif [ "${DELETE_ALL}" == "yes" ]; then
+				my_input=0
+			else
+				for line in $(<${TMP}/files/${input}); do
+					if (( ${fcount} > 0 )); then
+						echo -n "${fcount}${PAR} "
+						echo "${line}"
+					else
+						if [[ ${mode} == 0 ]] ; then
+							echo "Below are the new config files for ${line}:"
+						else
+							local my_title="Please select a file to process for ${line}"
+						fi
+					fi
+					fcount=${fcount}+1
+				done > ${TMP}/menuitems
+
+				if [[ ${mode} == 0 ]] ; then
+					cat ${TMP}/menuitems
+					echo -n "Please select a file to process (-1 to exit this file): "
+					my_input=$(read_int)
+				else
+					dialog --title "${title}" --menu "${my_title}" \
+						0 0 0 $(echo -e "$(<${TMP}/menuitems)\n${fcount} Exit") \
+						2> ${TMP}/input || die "User termination!" 0
+					my_input=$(<${TMP}/input)
+				fi
+			fi # OVERWRITE_ALL
+
+			if [[ ${my_input} == 0 ]] ; then
+				my_input=1
+			elif [[ ${my_input} == -1 ]] ; then
+				input=0
+				return
+			elif [[ ${my_input} == ${fcount} ]] ; then
+				break
+			fi
+		done
+		if [[ ${my_input} == ${fcount} ]] ; then
+			break
+		fi
+
+		fcount=${my_input}+1
+
+		file=$(sed -e "${fcount}p;d" ${TMP}/files/${input})
+		ofile=$(head -n1 ${TMP}/files/${input})
+
+		do_cfg "${file}" "${ofile}"
+
+		sed -e "${fcount}!p;d" ${TMP}/files/${input} > ${TMP}/files/sed
+		mv ${TMP}/files/sed ${TMP}/files/${input}
+
+		if [[ ${my_input} == -1 ]] ; then
+			break
+		fi
+	done
+	echo
+	rm ${TMP}/files/${input}
+	count=${count}-1
+}
+
+function do_cfg() {
+
+	local file="${1}"
+	local ofile="${2}"
+	local -i my_input=0
+
+	until (( ${my_input} == -1 )) || [ ! -f ${file} ]; do
+		if [[ "${OVERWRITE_ALL}" == "yes" ]] && ! user_special "${ofile}"; then
+			my_input=1
+		elif [[ "${DELETE_ALL}" == "yes" ]] && ! user_special "${ofile}"; then
+			my_input=2
+		else
+			showdiffcmd=$(echo "${diff_command}" |
+				sed -e "s:%file1:${ofile}:" -e "s:%file2:${file}:")
+
+			if [ "${using_editor}" == 0 ]; then
+				(
+					echo "Showing differences between ${ofile} and ${file}"
+					${showdiffcmd}
+				) | ${pager}
+			else
+				echo "Beginning of differences between ${ofile} and ${file}"
+				${showdiffcmd}
+				echo "End of differences between ${ofile} and ${file}"
+			fi
+			if [ -L "${file}" ]; then
+				echo
+				echo "-------------------------------------------------------------"
+				echo "NOTE: File is a symlink to another file. REPLACE recommended."
+				echo "      The original file may simply have moved. Please review."
+				echo "-------------------------------------------------------------"
+				echo
+			fi
+			echo -n "File: ${file}
+1) Replace original with update
+2) Delete update, keeping original as is
+3) Interactively merge original with update
+4) Show differences again
+Please select from the menu above (-1 to ignore this update): "
+			my_input=$(read_int)
+		fi
+
+		case ${my_input} in
+			1) echo "Replacing ${ofile} with ${file}"
+			   mv ${mv_opts} ${file} ${ofile}
+			   [ -n "${OVERWRITE_ALL}" ] && my_input=-1
+			   continue
+			   ;;
+			2) echo "Deleting ${file}"
+			   rm ${rm_opts} ${file}
+			   [ -n "${DELETE_ALL}" ] && my_input=-1
+			   continue
+			   ;;
+			3) do_merge "${file}" "${ofile}"
+			   my_input=${?}
+#			   [ ${my_input} == 255 ] && my_input=-1
+			   continue
+			   ;;
+			4) continue
+			   ;;
+			*) continue
+			   ;;
+		esac
+	done
+}
+
+function do_merge() {
+
+	local file="${1}"
+	local ofile="${2}"
+	local mfile="${2}.merged"
+	local -i my_input=0
+	echo "${file} ${ofile} ${mfile}"
+
+	if [ -e ${mfile} ] ; then
+		echo "A previous version of the merged file exists, cleaning..."
+		rm ${rm_opts} ${mfile}
+	fi
+
+	until (( ${my_input} == -1 )); do
+		echo "Merging ${file} and ${ofile}"
+		$(echo "${merge_command}" |
+		 sed -e "s:%merged:${mfile}:g" \
+		 	 -e "s:%orig:${ofile}:g" \
+			 -e "s:%new:${file}:g")
+		until (( ${my_input} == -1 )); do
+			echo -n "1) Replace ${ofile} with merged file
+2) Show differences between merged file and original
+3) Remerge original with update
+4) Edit merged file
+5) Return to the previous menu
+Please select from the menu above (-1 to exit, losing this merge): "
+			my_input=$(read_int)
+			case ${my_input} in
+				1) echo "Replacing ${ofile} with ${mfile}"
+				   if [[ ${USERLAND} == GNU ]]; then
+				       chmod --reference="${ofile}" "${mfile}"
+				   else
+				       chmod $(stat -f %Mp%Lp "${ofile}") "${mfile}"
+				   fi
+				   mv ${mv_opts} ${mfile} ${ofile}
+				   rm ${rm_opts} ${file}
+				   return 255
+				   ;;
+				2) ( echo "Showing differences between ${ofile} and ${mfile}"
+					 $(echo "${diff_command}" | \
+					  sed -e "s:%file1:${ofile}:" \
+					  	  -e "s:%file2:${mfile}:") ) | ${pager}
+				   continue
+				   ;;
+				3) break
+				   ;;
+				4) ${EDITOR:-nano -w} "${mfile}"
+				   continue
+					 ;;
+				5) rm ${rm_opts} ${mfile}
+				   return 0
+				   ;;
+				*) continue
+				   ;;
+			esac
+		done
+	done
+	rm ${rm_opts} ${mfile}
+	return 255
+}
+
+function die() {
+	trap "" TERM
+	trap "" KILL
+	echo "Exiting: ${1}"
+
+	if [ ${2} -eq 0 ]; then
+		scan > /dev/null
+		[ ${count} -gt 0 ] && echo "NOTE: ${count} updates remaining"
+	fi
+
+	rm -rf ${TMP}
+	exit ${2}
+}
+
+#
+# Run the script
+#
+scriptname=$(basename $0)
+
+trap die term
+
+type portageq > /dev/null || exit $?
+eval $(portageq envvar -v CONFIG_PROTECT \
+	CONFIG_PROTECT_MASK PORTAGE_CONFIGROOT PORTAGE_TMPDIR ROOT USERLAND)
+export PORTAGE_TMPDIR
+
+[ -w ${PORTAGE_CONFIGROOT}etc ] || die "Need write access to ${PORTAGE_CONFIGROOT}etc" 1
+#echo $PORTAGE_TMPDIR
+#echo $CONFIG_PROTECT
+#echo $CONFIG_PROTECT_MASK
+#export PORTAGE_TMPDIR=$(/usr/lib/portage/bin/portageq envvar PORTAGE_TMPDIR)
+
+TMP="${PORTAGE_TMPDIR}/$$"
+rm -rf ${TMP} 2> /dev/null
+mkdir ${TMP} || die "failed mkdir command!" 1
+
+# I need the CONFIG_PROTECT value
+#CONFIG_PROTECT=$(/usr/lib/portage/bin/portageq envvar CONFIG_PROTECT)
+#CONFIG_PROTECT_MASK=$(/usr/lib/portage/bin/portageq envvar CONFIG_PROTECT_MASK)
+
+# load etc-config's configuration
+EU_AUTOMERGE=$(get_config eu_automerge)
+rm_opts=$(get_config rm_opts)
+mv_opts=$(get_config mv_opts)
+cp_opts=$(get_config cp_opts)
+pager=$(get_config pager)
+diff_command=$(get_config diff_command)
+using_editor=$(get_config using_editor)
+merge_command=$(get_config merge_command)
+declare -i mode=$(get_config mode)
+[ -z ${mode} ] && mode=0
+[ -z "${pager}" ] && pager="cat"
+
+#echo "rm_opts: $rm_opts, mv_opts: $mv_opts, cp_opts: $cp_opts"
+#echo "pager: $pager, diff_command: $diff_command, merge_command: $merge_command"
+
+if (( ${mode} == 0 )); then
+	PAR=")"
+else
+	PAR=""
+fi
+
+declare -i count=0
+declare input=0
+declare title="Gentoolkit's etc-update tool!"
+
+scan
+
+until (( ${input} == -1 )); do
+	if (( ${count} == 0 )); then
+		die "Nothing left to do; exiting. :)" 0
+	fi
+	sel_file
+	if (( ${input} != -1 )); then
+		do_file
+	fi
+done
+
+die "User termination!" 0
Index: /vendor/portage/current/bin/find-requires
===================================================================
--- /vendor/portage/current/bin/find-requires	(revision 3419)
+++ /vendor/portage/current/bin/find-requires	(revision 3419)
@@ -0,0 +1,44 @@
+#!/bin/sh
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: find-requires 3483 2006-06-10 21:40:40Z genone $
+
+# note this works for both a.out and ELF executables
+# it also auto-generates requirment lines for shell scripts
+
+ulimit -c 0
+
+filelist=$(sed "s/['\"]/\\\&/g")
+exelist=$(echo $filelist | $XARGS file | grep ":.*executable" | cut -d: -f1 )
+scriptlist=$(echo $filelist | $XARGS file | egrep ":.* (commands|script) " | cut -d: -f1 )
+liblist=$(echo $filelist | $XARGS file | grep ":.*shared object" | cut -d : -f1 )
+
+for f in $exelist; do
+    if [ -x $f ]; then
+	ldd $f | awk '/=>/ { print $1 }'
+    fi
+done | sort -u | sed "s/['\"]/\\\&/g" | $XARGS -n 1 basename | grep -v 'libNoVersion.so' | sort -u
+
+for f in $liblist; do
+    ldd $f | awk '/=>/ { print $1 }'
+done | sort -u | sed "s/['\"]/\\\&/g" | $XARGS -n 1 basename | grep -v 'libNoVersion.so' | sort -u
+
+for f in $scriptlist; do
+    if [ -x $f ]; then
+	head -1 $f | sed -e 's/^\#\![ 	]*//' | cut -d" " -f1
+    fi
+done | sort -u
+
+#for f in $liblist $exelist ; do
+#    objdump -p $f | awk '
+#	BEGIN { START=0; LIBNAME=""; }
+#	/Version References:/ { START=1; }
+#	/required from/ && (START==1) {
+#	    sub(/:/, "", $3);
+#	    LIBNAME=$3;
+#	}
+#	(START==1) && (LIBNAME!="") && ($4~/^GLIBC_*/) { print LIBNAME "(" $4 ")"; }
+#	/^$/ { START=0; }
+#    '
+#done | sort -u
+
Index: /vendor/portage/current/bin/fix-db.py
===================================================================
--- /vendor/portage/current/bin/fix-db.py	(revision 3419)
+++ /vendor/portage/current/bin/fix-db.py	(revision 3419)
@@ -0,0 +1,181 @@
+#!/usr/bin/python
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: fix-db.py 4884 2006-10-31 04:23:06Z zmedico $
+
+import os,sys,re
+
+try:
+	import portage
+except ImportError:
+	from os import path as osp
+	sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
+	import portage
+
+from stat import *
+from output import *
+from portage import lockfile,unlockfile,VDB_PATH,root
+
+
+mylog = open("/var/log/emerge_fix-db.log", "a")
+def writemsg(msg):
+	if msg[-1] != '\n':
+		msg += "\n"
+	sys.stderr.write(msg)
+	sys.stderr.flush()
+	mylog.write(msg)
+	mylog.flush()
+
+def fix_global_counter(value):
+	myf = open("/var/cache/edb/counter")
+	newvalue = value+1000
+	myf.write(str(newvalue))
+	myf.flush()
+	myf.close()
+	return newvalue
+
+bad = {}
+counters = {}
+times = {}
+
+try:
+	real_counter = long(open("/var/cache/edb/counter").read())
+except SystemExit, e:
+	raise  # This needs to be propogated
+except:
+	writemsg("ERROR: Real counter is invalid.\n")
+	real_counter = 0
+
+vardbdir = root+VDB_PATH+"/"
+for cat in os.listdir(vardbdir):
+	catdir = vardbdir+cat+"/"
+	if not os.path.isdir(catdir):
+		writemsg("Invalid file: '%s'\n" % catdir[:-1])
+		continue
+	for pkg in os.listdir(catdir):
+		pkgdir = catdir+pkg+"/"
+		catpkg = cat+"/"+pkg
+
+		if not os.path.isdir(catdir):
+			writemsg("Invalid file: '%s'\n" % pkgdir)
+			continue
+			
+		bad[catpkg] = []
+		
+		pkgdirlist = os.listdir(pkgdir)
+		if not pkgdirlist:
+			writemsg("ERROR: Package directory is empty for '%s'\n" % catpkg)
+			writemsg("       Deleting this directory. Remerge if you want it back.\n")
+			os.rmdir(pkgdir)
+			del bad[catpkg]
+			continue
+		
+		if "CONTENTS" not in pkgdirlist:
+			bad[catpkg] += ["CONTENTS is missing"]
+			times[catpkg] = -1
+			writemsg("ERROR: Contents file is missing from the package directory.\n")
+			writemsg("       '%s' is corrupt and should be deleted.\n" % catpkg)
+		else:
+			times[catpkg] = None
+			for line in open(pkgdir+"CONTENTS").readlines():
+				mysplit = line.split()
+				if mysplit[0] == "obj":
+					try:
+						times[catpkg] = long(mysplit[-1])
+					except SystemExit, e:
+						raise  # This needs to be propogated
+					except:
+						times[catpkg] = -1
+						bad[catpkg] += ["CONTENTS is corrupt"]
+						writemsg("ERROR: Corrupt CONTENTS file in '%s'\n" % catpkg)
+						writemsg("       This package should be deleted.\n")
+					break
+			if times[catpkg] == None:
+				times[catpkg] = os.stat(pkgdir+"CONTENTS")[ST_MTIME]
+
+		if "COUNTER" not in pkgdirlist:
+			bad[catpkg] += ["COUNTER is missing"]
+			writemsg("ERROR: COUNTER file missing from '%s'.\n" % catpkg)
+			counters[catpkg] = -1
+		else:
+			try:
+				counters[catpkg] = long(open(pkgdir+"COUNTER").read().strip())
+				if counters[catpkg] > real_counter:
+					writemsg("ERROR: Global counter is lower than the '%s' COUNTER." % catpkg)
+					real_counter = fix_global_counter(counters[catpkg])
+			except SystemExit, e:
+				raise  # This needs to be propogated
+			except:
+				bad[catpkg] += ["COUNTER is corrupt"]
+				counters[catpkg] = -1
+
+		if "SLOT" not in pkgdirlist:
+			writemsg("ERROR: SLOT file missing from '%s'.\n" % catpkg)
+			writemsg("       RE-MERGE this exact package version or unmerge and remerge.\n")
+			bad[catpkg] += ["SLOT is missing"]
+		else:
+			myslot = open(pkgdir+"SLOT").read()
+			if myslot and myslot[-1]=="\n":
+				#writemsg("WARN: SLOT file has a newline. '%s'\n" % catpkg)
+				myslot = myslot[:-1]
+			if not myslot:
+				bad[catpkg] += ["SLOT is empty"]
+				writemsg("ERROR: SLOT file is empty for '%s'.\n" % catpkg)
+				writemsg("       RE-MERGE this exact package version or unmerge and remerge it.\n")
+			elif re.search("[^-a-zA-Z0-9\._]", myslot):
+				bad[catpkg] += ["SLOT is corrupt"]
+				writemsg("ERROR: SLOT file is corrupt for '%s'.\n" % catpkg)
+				writemsg("       RE-MERGE this exact package version or unmerge and remerge it.\n")
+			elif myslot.strip() != myslot:
+				writemsg("WARN: SLOT file has invalid characters. '%s'\n" % catpkg)
+				bad[catpkg] += ["SLOT is invalid"]
+
+		if not bad[catpkg]:
+			del bad[catpkg]
+
+
+actions = {}
+writemsg("\n\n")
+for catpkg in bad.keys():
+	bad[catpkg].sort()
+
+	mystr = ""
+	for x in bad[catpkg]:
+		mystr += "   "+str(x)+"\n"
+
+	if bad[catpkg] == ["CONTENTS is missing", "SLOT is missing"]:
+		writemsg("%s: (possibly injected)\n%s\n" % (green(catpkg), mystr))
+		actions[catpkg] = ["ignore"]
+	elif bad[catpkg] == ["SLOT is empty"]:
+		writemsg("%s: (old package) []\n%s\n" % (yellow(catpkg), mystr))
+		actions[catpkg] = ["remerge"]
+	else:
+		writemsg("%s: (damaged/invalid) []\n%s\n" % (red(catpkg), mystr))
+		actions[catpkg] = ["merge exact"]
+
+if (len(sys.argv) > 1) and (sys.argv[1] == "--fix"):
+	writemsg("These are only directions, at the moment.")
+	for catpkg in actions.keys():
+		action = actions[catpkg]
+		writemsg("We will now '%s' '%s'..." % (action, catpkg))
+		#if action == 
+else:
+	#writemsg("Run with '--fix' to attempt automatic correction.")
+	pass
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: /vendor/portage/current/bin/fixdbentries
===================================================================
--- /vendor/portage/current/bin/fixdbentries	(revision 3419)
+++ /vendor/portage/current/bin/fixdbentries	(revision 3419)
@@ -0,0 +1,20 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: fixdbentries 3483 2006-06-10 21:40:40Z genone $
+
+# Script to adjust the contents of the DB entries after a package move.
+# Fairly straight forward... ./movedbentry 'from/here' 'to/here' /over/here
+
+VAR=$1
+NEW=$2
+SPATH=$3
+
+grep -FrZl "${VAR}" "${SPATH}" |
+sed "s#${SPATH}[^\d000]\+/CONTENTS\d000##g" |
+$XARGS -0 sed -i -e "
+s#${VAR}\$#${NEW}#g; 
+s#${VAR}\([[:space:]]\)#${NEW}\1#g; 
+s#${VAR}\(-[^a-zA-Z]\)#${NEW}\1#g; 
+s#${VAR}\([^a-zA-Z0-9-]\)#${NEW}\1#g
+"
Index: /vendor/portage/current/bin/fixpackages
===================================================================
--- /vendor/portage/current/bin/fixpackages	(revision 3419)
+++ /vendor/portage/current/bin/fixpackages	(revision 3419)
@@ -0,0 +1,31 @@
+#!/usr/bin/python
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: fixpackages 5075 2006-11-17 15:06:39Z zmedico $
+
+import os,sys
+os.environ["PORTAGE_CALLER"]="fixpackages"
+try:
+	import portage
+except ImportError:
+	from os import path as osp
+	sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
+	import portage
+
+mysettings = portage.settings
+mytrees = portage.db
+mtimedb = portage.mtimedb
+
+try:
+	os.nice(int(mysettings.get("PORTAGE_NICENESS", "0")))
+except (OSError, ValueError), e:
+	portage.writemsg("!!! Failed to change nice value to '%s'\n" % \
+		mysettings["PORTAGE_NICENESS"])
+	portage.writemsg("!!! %s\n" % str(e))
+	del e
+
+portage.global_updates(mysettings, mytrees, mtimedb["updates"])
+
+print
+print "Done."
+print
Index: /vendor/portage/current/bin/fowners
===================================================================
--- /vendor/portage/current/bin/fowners	(revision 3419)
+++ /vendor/portage/current/bin/fowners	(revision 3419)
@@ -0,0 +1,7 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: fowners 3483 2006-06-10 21:40:40Z genone $
+
+slash=/
+exec chown "${@/#${slash}/${D}${slash}}"
Index: /vendor/portage/current/bin/fperms
===================================================================
--- /vendor/portage/current/bin/fperms	(revision 3419)
+++ /vendor/portage/current/bin/fperms	(revision 3419)
@@ -0,0 +1,7 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: fperms 3483 2006-06-10 21:40:40Z genone $
+
+slash=/
+exec chmod "${@/#${slash}/${D}${slash}}"
Index: /vendor/portage/current/bin/isolated-functions.sh
===================================================================
--- /vendor/portage/current/bin/isolated-functions.sh	(revision 3419)
+++ /vendor/portage/current/bin/isolated-functions.sh	(revision 3419)
@@ -0,0 +1,256 @@
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header$
+
+quiet_mode() {
+	[[ ${PORTAGE_QUIET} -eq 1 ]]
+}
+
+vecho() {
+	quiet_mode || echo "$@"
+}
+
+# Internal logging function, don't use this in ebuilds
+elog_base() {
+	local messagetype
+	[ -z "${1}" -o -z "${T}" -o ! -d "${T}/logging" ] && return 1
+	case "${1}" in
+		INFO|WARN|ERROR|LOG|QA)
+			messagetype="${1}"
+			shift
+			;;
+		*)
+			vecho -e " ${BAD}*${NORMAL} Invalid use of internal function elog_base(), next message will not be logged"
+			return 1
+			;;
+	esac
+	echo -e "$*" >> ${T}/logging/${EBUILD_PHASE:-other}.${messagetype}
+	return 0
+}
+
+eqawarn() {
+	elog_base QA "$*"
+	vecho -e " ${WARN}*${NORMAL} $*" >&2
+	return 0
+}
+
+elog() {
+	elog_base LOG "$*"
+	echo -e " ${GOOD}*${NORMAL} $*"
+	return 0
+}
+
+esyslog() {
+	local pri=
+	local tag=
+
+	if [ -x /usr/bin/logger ]
+	then
+		pri="$1"
+		tag="$2"
+
+		shift 2
+		[ -z "$*" ] && return 0
+
+		/usr/bin/logger -p "${pri}" -t "${tag}" -- "$*"
+	fi
+
+	return 0
+}
+
+einfo() {
+	elog_base INFO "$*"
+	[[ ${RC_ENDCOL} != "yes" && ${LAST_E_CMD} == "ebegin" ]] && echo
+	echo -e " ${GOOD}*${NORMAL} $*"
+	LAST_E_CMD="einfo"
+	return 0
+}
+
+einfon() {
+	elog_base INFO "$*"
+	[[ ${RC_ENDCOL} != "yes" && ${LAST_E_CMD} == "ebegin" ]] && echo
+	echo -ne " ${GOOD}*${NORMAL} $*"
+	LAST_E_CMD="einfon"
+	return 0
+}
+
+ewarn() {
+	elog_base WARN "$*"
+	[[ ${RC_ENDCOL} != "yes" && ${LAST_E_CMD} == "ebegin" ]] && echo
+	echo -e " ${WARN}*${NORMAL} ${RC_INDENTATION}$*"
+	LAST_E_CMD="ewarn"
+	return 0
+}
+
+eerror() {
+	elog_base ERROR "$*"
+	[[ ${RC_ENDCOL} != "yes" && ${LAST_E_CMD} == "ebegin" ]] && echo
+	echo -e " ${BAD}*${NORMAL} ${RC_INDENTATION}$*"
+	LAST_E_CMD="eerror"
+	return 0
+}
+
+ebegin() {
+	local msg="$*" dots spaces=${RC_DOT_PATTERN//?/ }
+	if [[ -n ${RC_DOT_PATTERN} ]] ; then
+		dots=$(printf "%$(( COLS - 3 - ${#RC_INDENTATION} - ${#msg} - 7 ))s" '')
+		dots=${dots//${spaces}/${RC_DOT_PATTERN}}
+		msg="${msg}${dots}"
+	else
+		msg="${msg} ..."
+	fi
+	einfon "${msg}"
+	[[ ${RC_ENDCOL} == "yes" ]] && echo
+	LAST_E_LEN=$(( 3 + ${#RC_INDENTATION} + ${#msg} ))
+	LAST_E_CMD="ebegin"
+	return 0
+}
+
+_eend() {
+	local retval=${1:-0} efunc=${2:-eerror} msg
+	shift 2
+
+	if [[ ${retval} == "0" ]] ; then
+		msg="${BRACKET}[ ${GOOD}ok${BRACKET} ]${NORMAL}"
+	else
+		if [[ -n $* ]] ; then
+			${efunc} "$*"
+		fi
+		msg="${BRACKET}[ ${BAD}!!${BRACKET} ]${NORMAL}"
+	fi
+
+	if [[ ${RC_ENDCOL} == "yes" ]] ; then
+		echo -e "${ENDCOL}  ${msg}"
+	else
+		[[ ${LAST_E_CMD} == ebegin ]] || LAST_E_LEN=0
+		printf "%$(( COLS - LAST_E_LEN - 6 ))s%b\n" '' "${msg}"
+	fi
+
+	return ${retval}
+}
+
+eend() {
+	local retval=${1:-0}
+	shift
+
+	_eend ${retval} eerror "$*"
+
+	return ${retval}
+}
+
+KV_major() {
+	[[ -z $1 ]] && return 1
+
+	local KV=$@
+	echo "${KV%%.*}"
+}
+
+KV_minor() {
+	[[ -z $1 ]] && return 1
+
+	local KV=$@
+	KV=${KV#*.}
+	echo "${KV%%.*}"
+}
+
+KV_micro() {
+	[[ -z $1 ]] && return 1
+
+	local KV=$@
+	KV=${KV#*.*.}
+	echo "${KV%%[^[:digit:]]*}"
+}
+
+KV_to_int() {
+	[[ -z $1 ]] && return 1
+
+	local KV_MAJOR=$(KV_major "$1")
+	local KV_MINOR=$(KV_minor "$1")
+	local KV_MICRO=$(KV_micro "$1")
+	local KV_int=$(( KV_MAJOR * 65536 + KV_MINOR * 256 + KV_MICRO ))
+
+	# We make version 2.2.0 the minimum version we will handle as
+	# a sanity check ... if its less, we fail ...
+	if [[ ${KV_int} -ge 131584 ]] ; then
+		echo "${KV_int}"
+		return 0
+	fi
+
+	return 1
+}
+
+_RC_GET_KV_CACHE=""
+get_KV() {
+	[[ -z ${_RC_GET_KV_CACHE} ]] \
+		&& _RC_GET_KV_CACHE=$(uname -r)
+
+	echo $(KV_to_int "${_RC_GET_KV_CACHE}")
+
+	return $?
+}
+
+unset_colors() {
+	COLS="25 80"
+	ENDCOL=
+
+	GOOD=
+	WARN=
+	BAD=
+	NORMAL=
+	HILITE=
+	BRACKET=
+}
+
+set_colors() {
+	COLS=${COLUMNS:-0}      # bash's internal COLUMNS variable
+	(( COLS == 0 )) && COLS=$(set -- $(stty size 2>/dev/null) ; echo $2)
+	(( COLS > 0 )) || (( COLS = 80 ))
+	COLS=$((${COLS} - 8))	# width of [ ok ] == 7
+	# Adjust COLS so that eend works properly on a standard BSD console.
+	[ "${TERM}" = "cons25" ] && COLS=$((${COLS} - 1))
+
+	ENDCOL=$'\e[A\e['${COLS}'C'    # Now, ${ENDCOL} will move us to the end of the
+	                               # column;  irregardless of character width
+	if [ -n "${PORTAGE_COLORMAP}" ] ; then
+		eval ${PORTAGE_COLORMAP}
+	else
+		GOOD=$'\e[32;01m'
+		WARN=$'\e[33;01m'
+		BAD=$'\e[31;01m'
+		HILITE=$'\e[36;01m'
+		BRACKET=$'\e[34;01m'
+	fi
+	NORMAL=$'\e[0m'
+}
+
+RC_ENDCOL="yes"
+RC_INDENTATION=''
+RC_DEFAULT_INDENT=2
+RC_DOT_PATTERN=''
+
+case "${NOCOLOR:-false}" in
+	yes|true)
+		unset_colors
+		;;
+	no|false)
+		set_colors
+		;;
+esac
+
+has() {
+	hasq "$@"
+}
+
+hasv() {
+	if hasq "$@" ; then
+		echo "$1"
+		return 0
+	fi
+	return 1
+}
+
+hasq() {
+	[[ " ${*:2} " == *" $1 "* ]]
+}
+
+true
Index: /vendor/portage/current/bin/md5check.py
===================================================================
--- /vendor/portage/current/bin/md5check.py	(revision 3419)
+++ /vendor/portage/current/bin/md5check.py	(revision 3419)
@@ -0,0 +1,100 @@
+#!/usr/bin/python -O
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: md5check.py 5606 2007-01-12 10:08:12Z zmedico $
+
+import os,sys
+os.environ["FEATURES"]="mirror cvs"
+try:
+	import portage
+except ImportError:
+	from os import path as osp
+	sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
+	import portage
+import portage_util
+
+def cstrip(mystr,mychars):
+	newstr = ""
+	for x in mystr:
+		if x not in mychars:
+			newstr += x
+	return newstr
+
+md5_list = {}
+bn_list  = []
+col_list = []
+
+hugelist = []
+for mycp in portage.db["/"]["porttree"].dbapi.cp_all():
+	hugelist += portage.db["/"]["porttree"].dbapi.cp_list(mycp)
+hugelist.sort()
+
+for mycpv in hugelist:
+	pv = mycpv.split("/")[-1]
+
+	newuri = portage.db["/"]["porttree"].dbapi.aux_get(mycpv,["SRC_URI"])[0]
+	newuri = newuri.split()
+
+	digestpath = portage.db["/"]["porttree"].dbapi.findname(mycpv)
+	digestpath = os.path.dirname(digestpath)+"/files/digest-"+pv
+	md5sums    = portage.digestParseFile(digestpath)
+	
+	if md5sums == None:
+		portage.writemsg("Missing digest: %s\n" % mycpv)
+		md5sums = {}
+
+	for x in md5sums.keys():
+		if x[0] == '/':
+			del md5sums[x]
+
+	#portage.writemsg("\n\ndigestpath: %s\n" % digestpath)
+	#portage.writemsg("md5sums: %s\n" % md5sums)
+	#portage.writemsg("newuri: %s\n" % newuri)
+
+	bn_list = []
+	for x in newuri:
+		if not x:
+			continue
+		if (x in [")","(",":","||"]) or (x[-1] == "?"):
+			# ignore it. :)
+			continue
+		x = cstrip(x,"()|?")
+		if not x:
+			continue
+
+		mybn = os.path.basename(x)
+		if mybn not in bn_list:
+			bn_list += [mybn]
+		else:
+			continue
+		
+		if mybn not in md5sums.keys():
+			portage_util.writemsg("Missing md5sum: %s in %s\n" % (mybn, mycpv))
+		else:
+			if mybn in md5_list.keys():
+				if (md5_list[mybn]["MD5"]  != md5sums[mybn]["MD5"]) or \
+				   (md5_list[mybn]["size"] != md5sums[mybn]["size"]):
+
+					# This associates teh md5 with each file. [md5/size]
+					md5joins = md5_list[mybn][2].split(",")
+					md5joins = (" ["+md5_list[mybn][0]+"/"+md5_list[mybn][1]+"],").join(md5joins)
+					md5joins += " ["+md5_list[mybn][0]+"/"+md5_list[mybn][1]+"]"
+
+					portage.writemsg("Colliding md5: %s of %s [%s/%s] and %s\n" % (mybn,mycpv,md5sums[mybn][0],md5sums[mybn][1],md5joins))
+					col_list += [mybn]
+				else:
+					md5_list[mybn][2] += ","+mycpv
+			else:
+				md5_list[mybn] = md5sums[mybn]+[mycpv]
+			del md5sums[mybn]
+		
+	#portage.writemsg(str(bn_list)+"\n")
+	for x in md5sums.keys():
+		if x not in bn_list:
+			portage.writemsg("Extra md5sum: %s in %s\n" % (x, mycpv))
+
+
+print col_list
+print
+print str(len(md5_list.keys()))+" unique distfile md5s."
+print str(len(bn_list))+" unique distfile names."
Index: /vendor/portage/current/bin/md5check.sh
===================================================================
--- /vendor/portage/current/bin/md5check.sh	(revision 3419)
+++ /vendor/portage/current/bin/md5check.sh	(revision 3419)
@@ -0,0 +1,31 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: md5check.sh 3483 2006-06-10 21:40:40Z genone $
+
+# pipe in the data.
+
+sort -u -                    > md5check.tmp
+grep '^Extra'   md5check.tmp > md5check.tmp.extra
+grep '^Missing' md5check.tmp > md5check.tmp.missing
+grep '^Coll'    md5check.tmp > md5check.tmp.colliding
+
+sed -i "
+s:^Col:\nCol:
+s:,:\n  :g
+s: of :\n  :g
+s: and :\n  :g" md5check.tmp.colliding
+sed -i "s/^[^ ]\+ md5sum: \(.*\) in \(.*\)$/  \2: \1/g" md5check.tmp.missing
+sed -i "s/^[^ ]\+ md5sum: \(.*\) in \(.*\)$/  \2: \1/g" md5check.tmp.extra
+
+#echo "Colliding files:" > md5check.colliding
+#sort -u md5check.tmp.colliding >> md5check.colliding
+cp md5check.tmp.colliding md5check.colliding
+
+echo "Missing from digest:" > md5check.missing
+sort -u md5check.tmp.missing >> md5check.missing
+
+echo "Extra files in digest:" > md5check.extra
+sort -u md5check.tmp.extra >> md5check.extra
+
+rm md5check.tmp*
Index: /vendor/portage/current/bin/misc-functions.sh
===================================================================
--- /vendor/portage/current/bin/misc-functions.sh	(revision 3419)
+++ /vendor/portage/current/bin/misc-functions.sh	(revision 3419)
@@ -0,0 +1,565 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header$
+#
+# Miscellaneous shell functions that make use of the ebuild env but don't need
+# to be included directly in ebuild.sh.
+#
+# We're sourcing ebuild.sh here so that we inherit all of it's goodness,
+# including bashrc trickery.  This approach allows us to do our miscellaneous
+# shell work withing the same env that ebuild.sh has, but without polluting
+# ebuild.sh itself with unneeded logic and shell code.
+#
+# XXX hack: clear the args so ebuild.sh doesn't see them
+MISC_FUNCTIONS_ARGS="$@"
+shift $#
+
+source "${PORTAGE_BIN_PATH:-/usr/lib/portage/bin}/ebuild.sh"
+
+install_symlink_html_docs() {
+	cd "${D}" || die "cd failed"
+	#symlink the html documentation (if DOC_SYMLINKS_DIR is set in make.conf)
+	if [ -n "${DOC_SYMLINKS_DIR}" ] ; then
+		local mydocdir docdir
+		for docdir in "${HTMLDOC_DIR:-does/not/exist}" "${PF}/html" "${PF}/HTML" "${P}/html" "${P}/HTML" ; do
+			if [ -d "usr/share/doc/${docdir}" ] ; then
+				mydocdir="/usr/share/doc/${docdir}"
+			fi
+		done
+		if [ -n "${mydocdir}" ] ; then
+			local mysympath
+			if [ -z "${SLOT}" -o "${SLOT}" = "0" ] ; then
+				mysympath="${DOC_SYMLINKS_DIR}/${CATEGORY}/${PN}"
+			else
+				mysympath="${DOC_SYMLINKS_DIR}/${CATEGORY}/${PN}-${SLOT}"
+			fi
+			einfo "Symlinking ${mysympath} to the HTML documentation"
+			dodir "${DOC_SYMLINKS_DIR}/${CATEGORY}"
+			dosym "${mydocdir}" "${mysympath}"
+		fi
+	fi
+}
+
+install_qa_check() {
+	cd "${D}" || die "cd failed"
+	prepall
+
+	# Now we look for all world writable files.
+	for i in $(find "${D}/" -type f -perm -2); do
+		vecho -ne '\a'
+		vecho "QA Security Notice:"
+		vecho "- ${i:${#D}:${#i}} will be a world writable file."
+		vecho "- This may or may not be a security problem, most of the time it is one."
+		vecho "- Please double check that $PF really needs a world writeable bit and file bugs accordingly."
+		sleep 1
+	done
+
+	if type -P scanelf > /dev/null && ! hasq binchecks ${RESTRICT}; then
+		local qa_var insecure_rpath=0 tmp_quiet=${PORTAGE_QUIET}
+		
+		# display warnings when using stricter because we die afterwards
+		if has stricter ${FEATURES} ; then
+			unset PORTAGE_QUIET
+		fi
+		
+		# Make sure we disallow insecure RUNPATH/RPATH's
+		# Don't want paths that point to the tree where the package was built
+		# (older, broken libtools would do this).  Also check for null paths
+		# because the loader will search $PWD when it finds null paths.
+		f=$(scanelf -qyRF '%r %p' "${D}" | grep -E "(${PORTAGE_BUILDDIR}|: |::|^:|^ )")
+		if [[ -n ${f} ]] ; then
+			vecho -ne '\a\n'
+			eqawarn "QA Notice: The following files contain insecure RUNPATH's"
+			eqawarn " Please file a bug about this at http://bugs.gentoo.org/"
+			eqawarn " with the maintaining herd of the package."
+			eqawarn "${f}"
+			vecho -ne '\a\n'
+			if has stricter ${FEATURES} ; then
+				insecure_rpath=1
+			else
+				vecho "Auto fixing rpaths for ${f}"
+				TMPDIR=${PORTAGE_BUILDDIR} scanelf -BXr ${f} -o /dev/null
+			fi
+		fi
+
+		# TEXTREL's are baaaaaaaad
+		# Allow devs to mark things as ignorable ... e.g. things that are
+		# binary-only and upstream isn't cooperating (nvidia-glx) ... we
+		# allow ebuild authors to set QA_TEXTRELS_arch and QA_TEXTRELS ...
+		# the former overrides the latter ... regexes allowed ! :)
+		qa_var="QA_TEXTRELS_${ARCH/-/_}"
+		[[ -n ${!qa_var} ]] && QA_TEXTRELS=${!qa_var}
+		[[ -n ${QA_STRICT_TEXTRELS} ]] && QA_TEXTRELS=""
+		export QA_TEXTRELS
+		f=$(scanelf -qyRF '%t %p' "${D}" | grep -v 'usr/lib/debug/')
+		if [[ -n ${f} ]] ; then
+			scanelf -qyRF '%T %p' "${PORTAGE_BUILDDIR}"/ &> "${T}"/scanelf-textrel.log
+			vecho -ne '\a\n'
+			eqawarn "QA Notice: The following files contain runtime text relocations"
+			eqawarn " Text relocations force the dynamic linker to perform extra"
+			eqawarn " work at startup, waste system resources, and may pose a security"
+			eqawarn " risk.  On some architectures, the code may not even function"
+			eqawarn " properly, if at all."
+			eqawarn " For more information, see http://hardened.gentoo.org/pic-fix-guide.xml"
+			eqawarn " Please include this file in your report:"
+			eqawarn " ${T}/scanelf-textrel.log"
+			eqawarn "${f}"
+			vecho -ne '\a\n'
+			die_msg="${die_msg} textrels,"
+			sleep 1
+		fi
+
+		# Also, executable stacks only matter on linux (and just glibc atm ...)
+		f=""
+		case ${CTARGET:-${CHOST}} in
+			*-linux-gnu*)
+			# Check for files with executable stacks, but only on arches which
+			# are supported at the moment.  Keep this list in sync with
+			# http://hardened.gentoo.org/gnu-stack.xml (Arch Status)
+			case ${CTARGET:-${CHOST}} in
+				arm*|i?86*|ia64*|m68k*|s390*|sh*|x86_64*)
+					# Allow devs to mark things as ignorable ... e.g. things
+					# that are binary-only and upstream isn't cooperating ...
+					# we allow ebuild authors to set QA_EXECSTACK_arch and
+					# QA_EXECSTACK ... the former overrides the latter ...
+					# regexes allowed ! :)
+
+					qa_var="QA_EXECSTACK_${ARCH/-/_}"
+					[[ -n ${!qa_var} ]] && QA_EXECSTACK=${!qa_var}
+					[[ -n ${QA_STRICT_EXECSTACK} ]] && QA_EXECSTACK=""
+					qa_var="QA_WX_LOAD_${ARCH/-/_}"
+					[[ -n ${!qa_var} ]] && QA_WX_LOAD=${!qa_var}
+					[[ -n ${QA_STRICT_WX_LOAD} ]] && QA_WX_LOAD=""
+					export QA_EXECSTACK QA_WX_LOAD
+					f=$(scanelf -qyRF '%e %p' "${D}" | grep -v 'usr/lib/debug/')
+					;;
+			esac
+			;;
+		esac
+		if [[ -n ${f} ]] ; then
+			# One more pass to help devs track down the source
+			scanelf -qyRF '%e %p' "${PORTAGE_BUILDDIR}"/ &> "${T}"/scanelf-execstack.log
+			vecho -ne '\a\n'
+			eqawarn "QA Notice: The following files contain executable stacks"
+			eqawarn " Files with executable stacks will not work properly (or at all!)"
+			eqawarn " on some architectures/operating systems.  A bug should be filed"
+			eqawarn " at http://bugs.gentoo.org/ to make sure the file is fixed."
+			eqawarn " For more information, see http://hardened.gentoo.org/gnu-stack.xml"
+			eqawarn " Please include this file in your report:"
+			eqawarn " ${T}/scanelf-execstack.log"
+			eqawarn "${f}"
+			vecho -ne '\a\n'
+			die_msg="${die_msg} execstacks"
+			sleep 1
+		fi
+
+		# Save NEEDED information
+		scanelf -qyRF '%p %n' "${D}" | sed -e 's:^:/:' > "${PORTAGE_BUILDDIR}"/build-info/NEEDED
+
+		if [[ ${insecure_rpath} -eq 1 ]] ; then
+			die "Aborting due to serious QA concerns with RUNPATH/RPATH"
+		elif [[ -n ${die_msg} ]] && has stricter ${FEATURES} ; then
+			die "Aborting due to QA concerns: ${die_msg}"
+		fi
+
+		# Run some sanity checks on shared libraries
+		for d in "${D}"lib* "${D}"usr/lib* ; do
+			f=$(scanelf -ByF '%S %p' "${d}"/lib*.so* | gawk '$2 == "" { print }')
+			if [[ -n ${f} ]] ; then
+				vecho -ne '\a\n'
+				eqawarn "QA Notice: The following shared libraries lack a SONAME"
+				eqawarn "${f}"
+				vecho -ne '\a\n'
+				sleep 1
+			fi
+
+			f=$(scanelf -ByF '%n %p' "${d}"/lib*.so* | gawk '$2 == "" { print }')
+			if [[ -n ${f} ]] ; then
+				vecho -ne '\a\n'
+				eqawarn "QA Notice: The following shared libraries lack NEEDED entries"
+				eqawarn "${f}"
+				vecho -ne '\a\n'
+				sleep 1
+			fi
+		done
+
+		PORTAGE_QUIET=${tmp_quiet}
+	fi
+
+	local unsafe_files=$(find "${D}" -type f '(' -perm -2002 -o -perm -4002 ')')
+	if [[ -n ${unsafe_files} ]] ; then
+		eqawarn "QA Notice: Unsafe files detected (set*id and world writable)"
+		eqawarn "${unsafe_files}"
+		die "Unsafe files found in \${D}.  Portage will not install them."
+	fi
+
+	if [[ -d ${D}/${D} ]] ; then
+		declare -i INSTALLTOD=0
+		for i in $(find "${D}/${D}/"); do
+			eqawarn "QA Notice: /${i##${D}/${D}} installed in \${D}/\${D}"
+			((INSTALLTOD++))
+		done
+		die "Aborting due to QA concerns: ${INSTALLTOD} files installed in ${D}/${D}"
+		unset INSTALLTOD
+	fi
+
+	# this should help to ensure that all (most?) shared libraries are executable
+	# and that all libtool scripts / static libraries are not executable
+	for i in "${D}"opt/*/lib{,32,64} \
+	         "${D}"lib{,32,64}       \
+	         "${D}"usr/lib{,32,64}   \
+	         "${D}"usr/X11R6/lib{,32,64} ; do
+		[[ ! -d ${i} ]] && continue
+
+		for j in "${i}"/*.so.* "${i}"/*.so ; do
+			[[ ! -e ${j} ]] && continue
+			if [[ -L ${j} ]] ; then
+				linkdest=$(readlink "${j}")
+				if [[ ${linkdest} == /* ]] ; then
+					vecho -ne '\a\n'
+					eqawarn "QA Notice: Found an absolute symlink in a library directory:"
+					eqawarn "           ${j#${D}} -> ${linkdest}"
+					eqawarn "           It should be a relative symlink if in the same directory"
+					eqawarn "           or a linker script if it crosses the /usr boundary."
+				fi
+				continue
+			fi
+			[[ -x ${j} ]] && continue
+			vecho "making executable: ${j#${D}}"
+			chmod +x "${j}"
+		done
+
+		for j in "${i}"/*.a "${i}"/*.la ; do
+			[[ ! -e ${j} ]] && continue
+			[[ -L ${j} ]] && continue
+			[[ ! -x ${j} ]] && continue
+			vecho "removing executable bit: ${j#${D}}"
+			chmod -x "${j}"
+		done
+	done
+
+	# When installing static libraries into /usr/lib and shared libraries into 
+	# /lib, we have to make sure we have a linker script in /usr/lib along side 
+	# the static library, or gcc will utilize the static lib when linking :(.
+	# http://bugs.gentoo.org/4411
+	abort="no"
+	for a in "${D}"usr/lib*/*.a ; do
+		s=${a%.a}.so
+		if [[ ! -e ${s} ]] ; then
+			s=${s%usr/*}${s##*/usr/}
+			if [[ -e ${s} ]] ; then
+				vecho -ne '\a\n'
+				eqawarn "QA Notice: Missing gen_usr_ldscript for ${s##*/}"
+	 			abort="yes"
+			fi
+		fi
+	done
+	[[ ${abort} == "yes" ]] && die "add those ldscripts"
+
+	# Make sure people don't store libtool files or static libs in /lib
+	f=$(ls "${D}"lib*/*.{a,la} 2>/dev/null)
+	if [[ -n ${f} ]] ; then
+		vecho -ne '\a\n'
+		eqawarn "QA Notice: Excessive files found in the / partition"
+		eqawarn "${f}"
+		vecho -ne '\a\n'
+		die "static archives (*.a) and libtool library files (*.la) do not belong in /"
+	fi
+
+	# Verify that the libtool files don't contain bogus $D entries.
+	abort="no"
+	for a in "${D}"usr/lib*/*.la ; do
+		s=${a##*/}
+		if grep -qs "${D}" "${a}" ; then
+			vecho -ne '\a\n'
+			eqawarn "QA Notice: ${s} appears to contain PORTAGE_TMPDIR paths"
+			abort="yes"
+		fi
+	done
+	[[ ${abort} == "yes" ]] && die "soiled libtool library files found"
+
+	# Evaluate misc gcc warnings
+	if [[ -n ${PORTAGE_LOG_FILE} && -r ${PORTAGE_LOG_FILE} ]] ; then
+		local m msgs=(
+			": warning: dereferencing type-punned pointer will break strict-aliasing rules$"
+			": warning: implicit declaration of function "
+			": warning: incompatible implicit declaration of built-in function "
+			": warning: is used uninitialized in this function$" # we'll ignore "may" and "might"
+			": warning: comparisons like X<=Y<=Z do not have their mathematical meaning$"
+			": warning: null argument where non-null required "
+		)
+		abort="no"
+		i=0
+		while [[ -n ${msgs[${i}]} ]] ; do
+			m=${msgs[$((i++))]}
+			# force C locale to work around slow unicode locales #160234
+			f=$(LC_ALL=C grep "${m}" "${PORTAGE_LOG_FILE}")
+			if [[ -n ${f} ]] ; then
+				vecho -ne '\a\n'
+				eqawarn "QA Notice: Package has poor programming practices which may compile"
+				eqawarn "           fine but exhibit random runtime failures."
+				eqawarn "${f}"
+				vecho -ne '\a\n'
+				abort="yes"
+			fi
+		done
+		f=$(cat "${PORTAGE_LOG_FILE}" | check-implicit-pointer-usage.py)
+		if [[ -n ${f} ]] ; then
+			vecho -ne '\a\n'
+			eqawarn "QA Notice: Package has poor programming practices which may compile"
+			eqawarn "           but will almost certainly crash on 64bit architectures."
+			eqawarn "${f}"
+			vecho -ne '\a\n'
+			abort="yes"
+		fi
+		[[ ${abort} == "yes" ]] && hasq stricter ${FEATURES} && die "poor code kills airplanes"
+	fi
+
+	# Portage regenerates this on the installed system.
+	rm -f "${D}"/usr/share/info/dir{,.gz,.bz2}
+
+	if hasq multilib-strict ${FEATURES} && \
+	   [[ -x /usr/bin/file && -x /usr/bin/find ]] && \
+	   [[ -n ${MULTILIB_STRICT_DIRS} && -n ${MULTILIB_STRICT_DENY} ]]
+	then
+		local abort=no firstrun=yes
+		MULTILIB_STRICT_EXEMPT=$(echo ${MULTILIB_STRICT_EXEMPT} | sed -e 's:\([(|)]\):\\\1:g')
+		for dir in ${MULTILIB_STRICT_DIRS} ; do
+			[[ -d ${D}/${dir} ]] || continue
+			for file in $(find ${D}/${dir} -type f | grep -v "^${D}/${dir}/${MULTILIB_STRICT_EXEMPT}"); do
+				if file ${file} | egrep -q "${MULTILIB_STRICT_DENY}" ; then
+					if [[ ${firstrun} == yes ]] ; then
+						echo "Files matching a file type that is not allowed:"
+						firstrun=no
+					fi
+					abort=yes
+					echo "   ${file#${D}//}"
+				fi
+			done
+		done
+		[[ ${abort} == yes ]] && die "multilib-strict check failed!"
+	fi
+}
+
+
+install_mask() {
+	local root="$1"
+	shift
+	local install_mask="$*"
+
+	# we don't want globbing for initial expansion, but afterwards, we do
+	local shopts=$-
+	set -o noglob
+	for no_inst in ${install_mask}; do
+		set +o noglob
+		quiet_mode || einfo "Removing ${no_inst}"
+		# normal stuff
+		rm -Rf ${root}/${no_inst} >&/dev/null
+
+		# we also need to handle globs (*.a, *.h, etc)
+		find "${root}" -path ${no_inst} -exec rm -fR {} \; >/dev/null
+	done
+	# set everything back the way we found it
+	set +o noglob
+	set -${shopts}
+}
+
+preinst_bsdflags() {
+	type -P chflags > /dev/null || return 0
+	type -P mtree > /dev/null || return 1
+	# Save all the file flags for restoration after installation.
+	mtree -c -p "${D}" -k flags > "${T}/bsdflags.mtree"
+	# Remove all the file flags so that the merge phase can do anything
+	# necessary.
+	chflags -R noschg,nouchg,nosappnd,nouappnd "${D}"
+	chflags -R nosunlnk,nouunlnk "${D}" 2>/dev/null
+}
+
+postinst_bsdflags() {
+	type -P chflags > /dev/null || return 0
+	type -P mtree > /dev/null || return 1
+	# Restore all the file flags that were saved before installation.
+	mtree -e -p "${ROOT}" -U -k flags < "${T}/bsdflags.mtree" &> /dev/null
+}
+
+preinst_mask() {
+	if [ -z "$IMAGE" ]; then
+		 eerror "${FUNCNAME}: IMAGE is unset"
+		 return 1
+	fi
+	# remove man pages, info pages, docs if requested
+	for f in man info doc; do
+		if hasq no${f} $FEATURES; then
+			INSTALL_MASK="${INSTALL_MASK} /usr/share/${f}"
+		fi
+	done
+
+	install_mask "${IMAGE}" ${INSTALL_MASK}
+
+	# remove share dir if unnessesary
+	if hasq nodoc $FEATURES -o hasq noman $FEATURES -o hasq noinfo $FEATURES; then
+		rmdir "${IMAGE}/usr/share" &> /dev/null
+	fi
+}
+
+preinst_sfperms() {
+	if [ -z "$IMAGE" ]; then
+		 eerror "${FUNCNAME}: IMAGE is unset"
+		 return 1
+	fi
+	# Smart FileSystem Permissions
+	if hasq sfperms $FEATURES; then
+		for i in $(find ${IMAGE}/ -type f -perm -4000); do
+			ebegin ">>> SetUID: [chmod go-r] $i "
+			chmod go-r "$i"
+			eend $?
+		done
+		for i in $(find ${IMAGE}/ -type f -perm -2000); do
+			ebegin ">>> SetGID: [chmod o-r] $i "
+			chmod o-r "$i"
+			eend $?
+		done
+	fi
+}
+
+preinst_suid_scan() {
+	if [ -z "$IMAGE" ]; then
+		 eerror "${FUNCNAME}: IMAGE is unset"
+		 return 1
+	fi
+	# total suid control.
+	if hasq suidctl $FEATURES; then
+		sfconf=/etc/portage/suidctl.conf
+		vecho ">>> Performing suid scan in ${IMAGE}"
+		for i in $(find ${IMAGE}/ -type f \( -perm -4000 -o -perm -2000 \) ); do
+			if [ -s "${sfconf}" ]; then
+				suid="$(grep ^${i/${IMAGE}/}$ ${sfconf})"
+				if [ "${suid}" = "${i/${IMAGE}/}" ]; then
+					vecho "- ${i/${IMAGE}/} is an approved suid file"
+				else
+					vecho ">>> Removing sbit on non registered ${i/${IMAGE}/}"
+					for x in 5 4 3 2 1 0; do echo -ne "\a"; sleep 0.25 ; done
+					vecho -ne "\a"
+					ls_ret=$(ls -ldh "${i}")
+					chmod ugo-s "${i}"
+					grep ^#${i/${IMAGE}/}$ ${sfconf} > /dev/null || {
+						# sandbox prevents us from writing directly
+						# to files outside of the sandbox, but this
+						# can easly be bypassed using the addwrite() function
+						addwrite "${sfconf}"
+						vecho ">>> Appending commented out entry to ${sfconf} for ${PF}"
+						echo "## ${ls_ret%${IMAGE}*}${ls_ret#*${IMAGE}}" >> ${sfconf}
+						echo "#${i/${IMAGE}/}" >> ${sfconf}
+						# no delwrite() eh?
+						# delwrite ${sconf}
+					}
+				fi
+			else
+				vecho "suidctl feature set but you are lacking a ${sfconf}"
+			fi
+		done
+	fi
+}
+
+preinst_selinux_labels() {
+	if [ -z "$IMAGE" ]; then
+		 eerror "${FUNCNAME}: IMAGE is unset"
+		 return 1
+	fi
+	if hasq selinux ${FEATURES}; then
+		# SELinux file labeling (needs to always be last in dyn_preinst)
+		# only attempt to label if setfiles is executable
+		# and 'context' is available on selinuxfs.
+		if [ -f /selinux/context -a -x /usr/sbin/setfiles -a -x /usr/sbin/selinuxconfig ]; then
+			vecho ">>> Setting SELinux security labels"
+			(
+				eval "$(/usr/sbin/selinuxconfig)" || \
+					die "Failed to determine SELinux policy paths.";
+	
+				addwrite /selinux/context;
+	
+				/usr/sbin/setfiles "${file_contexts_path}" -r "${IMAGE}" "${IMAGE}";
+			) || die "Failed to set SELinux security labels."
+		else
+			# nonfatal, since merging can happen outside a SE kernel
+			# like during a recovery situation
+			vecho "!!! Unable to set SELinux security labels"
+		fi
+	fi
+}
+
+dyn_package() {
+	cd "${PORTAGE_BUILDDIR}/image"
+	install_mask "${PORTAGE_BUILDDIR}/image" ${PKG_INSTALL_MASK}
+	local pkg_dest="${PKGDIR}/All/${PF}.tbz2"
+	local pkg_tmp="${PKGDIR}/All/${PF}.tbz2.$$"
+	local tar_options=""
+	[ "${PORTAGE_QUIET}" == "1" ] ||  tar_options="${tar_options} -v"
+	# Sandbox is disabled in case the user wants to use a symlink
+	# for $PKGDIR and/or $PKGDIR/All.
+	export SANDBOX_ON="0"
+	tar ${tar_options} -cf - . | bzip2 -f > "${pkg_tmp}" || \
+		die "Failed to create tarball"
+	cd ..
+	export PYTHONPATH=${PORTAGE_PYM_PATH:-/usr/lib/portage/pym}
+	python -c "import xpak; t=xpak.tbz2('${pkg_tmp}'); t.recompose('${PORTAGE_BUILDDIR}/build-info')"
+	if [ $? -ne 0 ]; then
+		rm -f "${pkg_tmp}"
+		die "Failed to append metadata to the tbz2 file"
+	fi
+	mv -f "${pkg_tmp}" "${pkg_dest}" || die "Failed to move tbz2 to ${pkg_dest}"
+	ln -sf "../All/${PF}.tbz2" "${PKGDIR}/${CATEGORY}/${PF}.tbz2" || die "Failed to create symlink in ${PKGDIR}/${CATEGORY}"
+	vecho ">>> Done."
+	cd "${PORTAGE_BUILDDIR}"
+	touch .packaged || die "Failed to 'touch .packaged' in ${PORTAGE_BUILDDIR}"
+}
+
+dyn_spec() {
+	tar czf "/usr/src/redhat/SOURCES/${PF}.tar.gz" "${O}/${PF}.ebuild" "${O}/files" || die "Failed to create base rpm tarball."
+
+	cat <<__END1__ > ${PF}.spec
+Summary: ${DESCRIPTION}
+Name: ${PN}
+Version: ${PV}
+Release: ${PR}
+Copyright: GPL
+Group: portage/${CATEGORY}
+Source: ${PF}.tar.gz
+Buildroot: ${D}
+%description
+${DESCRIPTION}
+
+${HOMEPAGE}
+
+%prep
+%setup -c
+
+%build
+
+%install
+
+%clean
+
+%files
+/
+__END1__
+
+}
+
+dyn_rpm() {
+	addwrite /usr/src/redhat/
+	addwrite ${RPMDIR}
+	dyn_spec
+	rpmbuild -bb "${PF}.spec" || die "Failed to integrate rpm spec file"
+	install -D "/usr/src/redhat/RPMS/i386/${PN}-${PV}-${PR}.i386.rpm" "${RPMDIR}/${CATEGORY}/${PN}-${PV}-${PR}.rpm" || die "Failed to move rpm"
+}
+
+if [ -n "${MISC_FUNCTIONS_ARGS}" ]; then
+	[ "$PORTAGE_DEBUG" == "1" ] && set -x
+	for x in ${MISC_FUNCTIONS_ARGS}; do
+		${x}
+	done
+fi
+
+:
Index: /vendor/portage/current/bin/newbin
===================================================================
--- /vendor/portage/current/bin/newbin	(revision 3419)
+++ /vendor/portage/current/bin/newbin	(revision 3419)
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: newbin 3483 2006-06-10 21:40:40Z genone $
+
+if [[ -z ${T} ]] || [[ -z ${2} ]] ; then
+	echo "$0: Need two arguments, old file and new file" 1>&2
+	exit 1
+fi
+
+rm -rf "${T}/${2}" && \
+cp -f "${1}" "${T}/${2}" && \
+exec dobin "${T}/${2}"
Index: /vendor/portage/current/bin/newconfd
===================================================================
--- /vendor/portage/current/bin/newconfd	(revision 3419)
+++ /vendor/portage/current/bin/newconfd	(revision 3419)
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: newconfd 3483 2006-06-10 21:40:40Z genone $
+
+if [[ -z ${T} ]] || [[ -z ${2} ]] ; then
+	echo "$0: Need two arguments, old file and new file" 1>&2
+	exit 1
+fi
+
+rm -rf "${T}/${2}" && \
+cp -f "${1}" "${T}/${2}" && \
+exec doconfd "${T}/${2}"
Index: /vendor/portage/current/bin/newdoc
===================================================================
--- /vendor/portage/current/bin/newdoc	(revision 3419)
+++ /vendor/portage/current/bin/newdoc	(revision 3419)
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: newdoc 3483 2006-06-10 21:40:40Z genone $
+
+if [[ -z ${T} ]] || [[ -z ${2} ]] ; then
+	echo "$0: Need two arguments, old file and new file" 1>&2
+	exit 1
+fi
+
+rm -rf "${T}/${2}" && \
+cp -f "${1}" "${T}/${2}" && \
+exec dodoc "${T}/${2}"
Index: /vendor/portage/current/bin/newenvd
===================================================================
--- /vendor/portage/current/bin/newenvd	(revision 3419)
+++ /vendor/portage/current/bin/newenvd	(revision 3419)
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: newenvd 3483 2006-06-10 21:40:40Z genone $
+
+if [[ -z ${T} ]] || [[ -z ${2} ]] ; then
+	echo "$0: Need two arguments, old file and new file" 1>&2
+	exit 1
+fi
+
+rm -rf "${T}/${2}" && \
+cp -f "${1}" "${T}/${2}" && \
+exec doenvd "${T}/${2}"
Index: /vendor/portage/current/bin/newexe
===================================================================
--- /vendor/portage/current/bin/newexe	(revision 3419)
+++ /vendor/portage/current/bin/newexe	(revision 3419)
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: newexe 3483 2006-06-10 21:40:40Z genone $
+
+if [[ -z ${T} ]] || [[ -z ${2} ]] ; then
+	echo "$0: Need two arguments, old file and new file" 1>&2
+	exit 1
+fi
+
+rm -rf "${T}/${2}" && \
+cp -f "${1}" "${T}/${2}" && \
+exec doexe "${T}/${2}"
Index: /vendor/portage/current/bin/newinitd
===================================================================
--- /vendor/portage/current/bin/newinitd	(revision 3419)
+++ /vendor/portage/current/bin/newinitd	(revision 3419)
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: newinitd 3483 2006-06-10 21:40:40Z genone $
+
+if [[ -z ${T} ]] || [[ -z ${2} ]] ; then
+	echo "$0: Need two arguments, old file and new file" 1>&2
+	exit 1
+fi
+
+rm -rf "${T}/${2}" && \
+cp -f "${1}" "${T}/${2}" && \
+exec doinitd "${T}/${2}"
Index: /vendor/portage/current/bin/newins
===================================================================
--- /vendor/portage/current/bin/newins	(revision 3419)
+++ /vendor/portage/current/bin/newins	(revision 3419)
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: newins 3483 2006-06-10 21:40:40Z genone $
+
+if [[ -z ${T} ]] || [[ -z ${2} ]] ; then
+	echo "$0: Need two arguments, old file and new file" 1>&2
+	exit 1
+fi
+
+rm -rf "${T}/${2}" && \
+cp -f "${1}" "${T}/${2}" && \
+exec doins "${T}/${2}"
Index: /vendor/portage/current/bin/newman
===================================================================
--- /vendor/portage/current/bin/newman	(revision 3419)
+++ /vendor/portage/current/bin/newman	(revision 3419)
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: newman 3483 2006-06-10 21:40:40Z genone $
+
+if [[ -z ${T} ]] || [[ -z ${2} ]] ; then
+	echo "$0: Need two arguments, old file and new file" 1>&2
+	exit 1
+fi
+
+rm -rf "${T}/${2}" && \
+cp -f "${1}" "${T}/${2}" && \
+exec doman "${T}/${2}"
Index: /vendor/portage/current/bin/newsbin
===================================================================
--- /vendor/portage/current/bin/newsbin	(revision 3419)
+++ /vendor/portage/current/bin/newsbin	(revision 3419)
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: newsbin 3483 2006-06-10 21:40:40Z genone $
+
+if [[ -z ${T} ]] || [[ -z ${2} ]] ; then
+	echo "$0: Need two arguments, old file and new file" 1>&2
+	exit 1
+fi
+
+rm -rf "${T}/${2}" && \
+cp -f "${1}" "${T}/${2}" && \
+exec dosbin "${T}/${2}"
Index: /vendor/portage/current/bin/pkgname
===================================================================
--- /vendor/portage/current/bin/pkgname	(revision 3419)
+++ /vendor/portage/current/bin/pkgname	(revision 3419)
@@ -0,0 +1,20 @@
+#!/usr/bin/python
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: pkgname 4884 2006-10-31 04:23:06Z zmedico $
+
+import sys, os
+try:
+	import portage
+except ImportError:
+	from os import path as osp
+	sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
+	import portage
+
+a=portage.pkgsplit(sys.argv[1])
+if a:
+	print a[0],a[1],a[2][1:]
+	sys.exit(0)
+else:
+	print '!!! Error: package name is invalid.'
+	sys.exit(1)
Index: /vendor/portage/current/bin/portage_gpg_update.sh
===================================================================
--- /vendor/portage/current/bin/portage_gpg_update.sh	(revision 3419)
+++ /vendor/portage/current/bin/portage_gpg_update.sh	(revision 3419)
@@ -0,0 +1,6 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: portage_gpg_update.sh 3483 2006-06-10 21:40:40Z genone $
+
+wget -O - http://www.gentoo.org/proj/en/devrel/roll-call/userinfo.xml | sed 's:.*\(0x[0-9a-fA-F]\+\)[^0-9a-fA-F].*:\1:gp;d' | xargs gpg -vvv --no-default-keyring  --no-permission-warning --homedir /usr/portage/metadata --keyring "gentoo.gpg" --keyserver subkeys.pgp.net --recv-keys &> gpg.log
Index: /vendor/portage/current/bin/portageq
===================================================================
--- /vendor/portage/current/bin/portageq	(revision 3419)
+++ /vendor/portage/current/bin/portageq	(revision 3419)
@@ -0,0 +1,348 @@
+#!/usr/bin/python -O
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: portageq 5597 2007-01-12 08:19:46Z antarus $
+
+import sys
+# This block ensures that ^C interrupts are handled quietly.
+try:
+	import signal
+
+	def exithandler(signum, frame):
+		signal.signal(signal.SIGINT, signal.SIG_IGN)
+		signal.signal(signal.SIGTERM, signal.SIG_IGN)
+		sys.exit(1)
+
+	signal.signal(signal.SIGINT, exithandler)
+	signal.signal(signal.SIGTERM, exithandler)
+
+except KeyboardInterrupt:
+	sys.exit(1)
+
+import os
+
+import types
+
+#-----------------------------------------------------------------------------
+#
+# To add functionality to this tool, add a function below.
+#
+# The format for functions is:
+#
+#   def function(argv):
+#       """<list of options for this function>
+#       <description of the function>
+#       """
+#       <code>
+#
+# "argv" is an array of the command line parameters provided after the command.
+#
+# Make sure you document the function in the right format.  The documentation
+# is used to display help on the function.
+#
+# You do not need to add the function to any lists, this tool is introspective,
+# and will automaticly add a command by the same name as the function!
+#
+
+
+def has_version(argv):
+	"""<root> <category/package>
+	Return code 0 if it's available, 1 otherwise.
+	"""
+	if (len(argv) < 2):
+		print "ERROR: insufficient parameters!"
+		sys.exit(2)
+	try:
+		mylist=portage.db[argv[0]]["vartree"].dbapi.match(argv[1])
+		if mylist:
+			sys.exit(0)
+		else:
+			sys.exit(1)
+	except KeyError:
+		sys.exit(1)
+has_version.uses_root = True
+
+
+def best_version(argv):
+	"""<root> <category/package>
+	Returns category/package-version (without .ebuild).
+	"""
+	if (len(argv) < 2):
+		print "ERROR: insufficient parameters!"
+		sys.exit(2)
+	try:
+		mylist=portage.db[argv[0]]["vartree"].dbapi.match(argv[1])
+		print portage.best(mylist)
+	except KeyError:
+		sys.exit(1)
+best_version.uses_root = True
+
+
+def mass_best_version(argv):
+	"""<root> [<category/package>]+
+	Returns category/package-version (without .ebuild).
+	"""
+	if (len(argv) < 2):
+		print "ERROR: insufficient parameters!"
+		sys.exit(2)
+	try:
+		for pack in argv[1:]:
+			mylist=portage.db[argv[0]]["vartree"].dbapi.match(pack)
+			print pack+":"+portage.best(mylist)
+	except KeyError:
+		sys.exit(1)
+mass_best_version.uses_root = True
+
+def metadata(argv):
+	"""<root> <pkgtype> <category/package> [<key>]+
+	Returns metadata values for the specified package.
+	"""
+	if (len(argv) < 4):
+		print >> sys.stderr, "ERROR: insufficient parameters!"
+		sys.exit(2)
+
+	root, pkgtype, pkgspec = argv[0:3]
+	metakeys = argv[3:]
+	type_map = {
+		"ebuild":"porttree",
+		"binary":"bintree",
+		"installed":"vartree"}
+	if pkgtype not in type_map:
+		print >> sys.stderr, "Unrecognized package type: '%s'" % pkgtype
+		sys.exit(1)
+	trees = portage.db
+	if os.path.realpath(root) == os.path.realpath(portage.settings["ROOT"]):
+		root = portage.settings["ROOT"] # contains the normalized $ROOT
+	try:
+			values = trees[root][type_map[pkgtype]].dbapi.aux_get(
+				pkgspec, metakeys)
+			for value in values:
+				print value
+	except KeyError:
+		print >> sys.stderr, "Package not found: '%s'" % pkgspec
+		sys.exit(1)
+
+metadata.uses_root = True
+
+def best_visible(argv):
+	"""<root> [<category/package>]+
+	Returns category/package-version (without .ebuild).
+	"""
+	if (len(argv) < 2):
+		print "ERROR: insufficient parameters!"
+		sys.exit(2)
+	try:
+		mylist=portage.db[argv[0]]["porttree"].dbapi.match(argv[1])
+		print portage.best(mylist)
+	except KeyError:
+		sys.exit(1)
+best_visible.uses_root = True
+
+
+def mass_best_visible(argv):
+	"""<root> [<category/package>]+
+	Returns category/package-version (without .ebuild).
+	"""
+	if (len(argv) < 2):
+		print "ERROR: insufficient parameters!"
+		sys.exit(2)
+	try:
+		for pack in argv[1:]:
+			mylist=portage.db[argv[0]]["porttree"].dbapi.match(pack)
+			print pack+":"+portage.best(mylist)
+	except KeyError:
+		sys.exit(1)
+mass_best_visible.uses_root = True
+
+
+def all_best_visible(argv):
+	"""<root>
+	Returns all best_visible packages (without .ebuild).
+	"""
+	if (len(argv) < 1):
+		print "ERROR: insufficient parameters!"
+	
+	#print portage.db[argv[0]]["porttree"].dbapi.cp_all()
+	for pkg in portage.db[argv[0]]["porttree"].dbapi.cp_all():
+		mybest=portage.best(portage.db[argv[0]]["porttree"].dbapi.match(pkg))
+		if mybest:
+			print mybest
+all_best_visible.uses_root = True
+
+
+def match(argv):
+	"""<root> <category/package>
+	Returns \n seperated list of category/package-version
+	"""
+	if (len(argv) < 2):
+		print "ERROR: insufficient parameters!"
+		sys.exit(2)
+	try:
+		print "\n".join(portage.db[argv[0]]["vartree"].dbapi.match(argv[1]))
+	except ValueError, e:
+		# Multiple matches thrown from cpv_expand
+		pkgs = e.args[0]
+		# An error has occurred so we writemsg to stderr and exit nonzero.
+		portage.writemsg("The following packages available:\n", noiselevel=-1)
+		for pkg in pkgs:
+			portage.writemsg("* %s\n" % pkg, noiselevel=-1)
+		portage.writemsg("\nPlease use a more specific atom.\n", noiselevel=-1)
+		sys.exit(1)
+	except KeyError, e:
+		portage.writemsg("%s\n" % str(e), noiselevel=-1)
+		sys.exit(1)
+match.uses_root = True
+
+
+def vdb_path(argv):
+	"""
+	Returns the path used for the var(installed) package database for the
+	set environment/configuration options.
+	"""
+	print portage.root+portage.VDB_PATH
+
+
+def gentoo_mirrors(argv):
+	"""
+	Returns the mirrors set to use in the portage configuration.
+	"""
+	print portage.settings["GENTOO_MIRRORS"]
+
+
+def portdir(argv):
+	"""
+	Returns the PORTDIR path.
+	"""
+	print portage.settings["PORTDIR"]
+
+
+def config_protect(argv):
+	"""
+	Returns the CONFIG_PROTECT paths.
+	"""
+	print portage.settings["CONFIG_PROTECT"]
+
+
+def config_protect_mask(argv):
+	"""
+	Returns the CONFIG_PROTECT_MASK paths.
+	"""
+	print portage.settings["CONFIG_PROTECT_MASK"]
+
+
+def portdir_overlay(argv):
+	"""
+	Returns the PORTDIR_OVERLAY path.
+	"""
+	print portage.settings["PORTDIR_OVERLAY"]
+
+
+def pkgdir(argv):
+	"""
+	Returns the PKGDIR path.
+	"""
+	print portage.settings["PKGDIR"]
+
+
+def distdir(argv):
+	"""
+	Returns the DISTDIR path.
+	"""
+	print portage.settings["DISTDIR"]
+
+
+def envvar(argv):
+	"""<variable>+
+	Returns a specific environment variable as exists prior to ebuild.sh.
+	Similar to: emerge --verbose --info | egrep '^<variable>='
+	"""
+	verbose = "-v" in argv
+	if verbose:
+		argv.pop(argv.index("-v"))
+
+	if len(argv) == 0:
+		print "ERROR: insufficient parameters!"
+		sys.exit(2)
+
+	for arg in argv:
+		if verbose:
+			print arg +"='"+ portage.settings[arg] +"'"
+		else:
+			print portage.settings[arg]
+
+
+#-----------------------------------------------------------------------------
+#
+# DO NOT CHANGE CODE BEYOND THIS POINT - IT'S NOT NEEDED!
+#
+
+def usage(argv):
+	rev="$Revision: 1.13.2.1 $"
+	ver= rev.split(' ')[1]
+	print ">>> Portage information query tool -- version "+ver
+	print ">>> Usage: portageq <command> [<option> ...]"
+	print ""
+	print "Available commands:"
+
+	#
+	# Show our commands -- we do this by scanning the functions in this
+	# file, and formatting each functions documentation.
+	#
+	for name in globals().keys():
+		# Drop python stuff, modules, and our own support functions.
+		if (name in ("usage", "__doc__", "__name__", "main", "os", "portage", "sys", "__builtins__", "types", "string")):
+			continue
+
+		# Drop non-functions
+		obj = globals()[name]
+		if  (type(obj) != types.FunctionType):
+			continue
+
+		doc = obj.__doc__
+		if (doc == None):
+			print "   "+name
+			print "      MISSING DOCUMENTATION!"
+			print ""
+			continue
+
+		lines = doc.split("\n")
+		print "   "+name+" "+lines[0].strip()
+		if (len(sys.argv) > 1):
+			if ("--help" not in sys.argv):
+				lines = lines[:-1]
+			for line in lines[1:]:
+				print "      "+line.strip()
+	if (len(sys.argv) == 1):
+		print "\nRun portageq with --help for info"
+
+def main():
+	if "-h" in sys.argv or "--help" in sys.argv:
+		usage(sys.argv)
+		sys.exit(os.EX_OK)
+	elif len(sys.argv) < 2:
+		usage(sys.argv)
+		sys.exit(os.EX_USAGE)
+
+	cmd = sys.argv[1]
+	try:
+		function = globals()[cmd]
+		uses_root = (getattr(function, "uses_root", False) and len(sys.argv) > 2)
+		if uses_root:
+			os.environ["ROOT"] = sys.argv[2]
+		global portage
+		try:
+			import portage
+		except ImportError:
+			from os import path as osp
+			sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
+			import portage
+		if uses_root:
+			sys.argv[2] = portage.root
+		function(sys.argv[2:])
+	except KeyError:
+		usage(sys.argv)
+		sys.exit(os.EX_USAGE)
+
+main()
+
+#-----------------------------------------------------------------------------
Index: /vendor/portage/current/bin/prepall
===================================================================
--- /vendor/portage/current/bin/prepall	(revision 3419)
+++ /vendor/portage/current/bin/prepall	(revision 3419)
@@ -0,0 +1,23 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: prepall 5442 2007-01-02 03:31:50Z vapier $
+
+source "${PORTAGE_BIN_PATH:-/usr/lib/portage/bin}"/isolated-functions.sh
+
+if type -P chflags > /dev/null && type -P mtree > /dev/null ; then
+	# Save all the file flags for restoration at the end of prepall.
+	mtree -c -p "${D}" -k flags > "${T}/bsdflags.mtree"
+	# Remove all the file flags so that prepall can do anything necessary.
+	chflags -R noschg,nouchg,nosappnd,nouappnd "${D}"
+	chflags -R nosunlnk,nouunlnk "${D}" 2>/dev/null
+fi
+
+prepallman
+prepallinfo
+prepallstrip
+
+if type -P chflags > /dev/null && type -P mtree > /dev/null; then
+	# Restore all the file flags that were saved at the beginning of prepall.
+	mtree -U -e -p "${D}" -k flags < "${T}/bsdflags.mtree" &> /dev/null
+fi
Index: /vendor/portage/current/bin/prepalldocs
===================================================================
--- /vendor/portage/current/bin/prepalldocs	(revision 3419)
+++ /vendor/portage/current/bin/prepalldocs	(revision 3419)
@@ -0,0 +1,25 @@
+#!/bin/bash
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: prepalldocs 5628 2007-01-13 04:52:55Z zmedico $
+
+if [[ -n $1 ]] ; then
+	vecho "${0##*/}: invalid usage; takes no arguments" 1>&2
+fi
+
+cd "${D}"
+[[ -d usr/share/doc ]] || exit 0
+
+# we dont want to compress the html subdir
+if [[ -d ${D}usr/share/doc/${PF}/html ]] ; then
+	mv "${D}"usr/share/doc/${PF}/html "${T}"/ecompressdir-html-backup || exit 1
+fi
+
+ecompressdir /usr/share/doc
+ret=$?
+
+if [[ -d ${T}/ecompressdir-html-backup ]] ; then
+	mv "${T}"/ecompressdir-html-backup "${D}"/usr/share/doc/${PF}/html
+fi
+
+exit ${ret}
Index: /vendor/portage/current/bin/prepallinfo
===================================================================
--- /vendor/portage/current/bin/prepallinfo	(revision 3419)
+++ /vendor/portage/current/bin/prepallinfo	(revision 3419)
@@ -0,0 +1,10 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: prepallinfo 5555 2007-01-11 18:50:51Z vapier $
+
+source "${PORTAGE_BIN_PATH:-/usr/lib/portage/bin}"/isolated-functions.sh
+
+[[ ! -d ${D}usr/share/info ]] && exit 0
+
+exec prepinfo
Index: /vendor/portage/current/bin/prepallman
===================================================================
--- /vendor/portage/current/bin/prepallman	(revision 3419)
+++ /vendor/portage/current/bin/prepallman	(revision 3419)
@@ -0,0 +1,17 @@
+#!/bin/bash
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: prepallman 5555 2007-01-11 18:50:51Z vapier $
+
+source "${PORTAGE_BIN_PATH:-/usr/lib/portage/bin}"/isolated-functions.sh
+
+ret=0
+
+find "${D}" -type d -name man > "${T}"/prepallman.filelist
+while read mandir ; do
+	mandir=${mandir#${D}}
+	prepman "${mandir%/man}"
+	((ret+=$?))
+done < "${T}"/prepallman.filelist
+
+exit ${ret}
Index: /vendor/portage/current/bin/prepallstrip
===================================================================
--- /vendor/portage/current/bin/prepallstrip	(revision 3419)
+++ /vendor/portage/current/bin/prepallstrip	(revision 3419)
@@ -0,0 +1,6 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: prepallstrip 3483 2006-06-10 21:40:40Z genone $
+
+exec prepstrip "${D}"
Index: /vendor/portage/current/bin/prepinfo
===================================================================
--- /vendor/portage/current/bin/prepinfo	(revision 3419)
+++ /vendor/portage/current/bin/prepinfo	(revision 3419)
@@ -0,0 +1,31 @@
+#!/bin/bash
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: prepinfo 5555 2007-01-11 18:50:51Z vapier $
+
+source "${PORTAGE_BIN_PATH:-/usr/lib/portage/bin}"/isolated-functions.sh
+
+if [[ -z $1 ]] ; then
+	infodir="/usr/share/info"
+else
+	if [[ -d ${D}$1/share/info ]] ; then
+		infodir="$1/share/info"
+	else
+		infodir="$1/info"
+	fi
+fi
+
+if [[ ! -d ${D}${infodir} ]] ; then
+	if [[ -n $1 ]] ; then
+		vecho "${0##*/}: '${infodir}' does not exist!"
+		exit 1
+	else
+		exit 0
+	fi
+fi
+
+find "${D}${infodir}" -type d -print0 | while read -d $'\0' x ; do
+	rm -f "${x}"/dir{,.info}{,.gz,.bz2}
+done
+
+exec ecompressdir "${infodir}"
Index: /vendor/portage/current/bin/preplib
===================================================================
--- /vendor/portage/current/bin/preplib	(revision 3419)
+++ /vendor/portage/current/bin/preplib	(revision 3419)
@@ -0,0 +1,29 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: preplib 5507 2007-01-10 04:22:27Z zmedico $
+
+source "${PORTAGE_BIN_PATH:-/usr/lib/portage/bin}"/isolated-functions.sh
+
+eqawarn "QA Notice: Deprecated call to 'preplib'"
+
+LIBDIR_VAR="LIBDIR_${ABI}"
+if [ -n "${ABI}" -a -n "${!LIBDIR_VAR}" ]; then
+	CONF_LIBDIR="${!LIBDIR_VAR}"
+fi
+unset LIBDIR_VAR
+
+if [ -z "${CONF_LIBDIR}" ]; then
+	# we need this to default to lib so that things dont break
+	CONF_LIBDIR="lib"
+fi
+
+if [ -z "$1" ] ; then
+	z="${D}usr/${CONF_LIBDIR}"
+else
+	z="${D}$1/${CONF_LIBDIR}"
+fi
+
+if [ -d "${z}" ] ; then
+	ldconfig -n -N "${z}"
+fi
Index: /vendor/portage/current/bin/prepman
===================================================================
--- /vendor/portage/current/bin/prepman	(revision 3419)
+++ /vendor/portage/current/bin/prepman	(revision 3419)
@@ -0,0 +1,30 @@
+#!/bin/bash
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: prepman 5555 2007-01-11 18:50:51Z vapier $
+
+source "${PORTAGE_BIN_PATH:-/usr/lib/portage/bin}"/isolated-functions.sh
+
+if [[ -z $1 ]] ; then 
+	mandir="${D}usr/share/man"
+else
+	mandir="${D}$1/man"
+fi
+
+if [[ ! -d ${mandir} ]] ; then
+	eqawarn "QA Notice: prepman called with non-existent dir '${mandir#${D}}'"
+	exit 0
+fi
+
+shopt -s nullglob
+
+really_is_mandir=0
+
+# use some heuristics to test if this is a real mandir
+for subdir in "${mandir}"/man* "${mandir}"/*/man* ; do
+	[[ -d ${subdir} ]] && really_is_mandir=1 && break
+done
+
+[[ ${really_is_mandir} == 1 ]] && exec ecompressdir "${mandir#${D}}"
+
+exit 0
Index: /vendor/portage/current/bin/prepstrip
===================================================================
--- /vendor/portage/current/bin/prepstrip	(revision 3419)
+++ /vendor/portage/current/bin/prepstrip	(revision 3419)
@@ -0,0 +1,96 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: prepstrip 5507 2007-01-10 04:22:27Z zmedico $
+
+source "${PORTAGE_BIN_PATH:-/usr/lib/portage/bin}"/isolated-functions.sh
+
+unset NOSTRIP
+if hasq nostrip ${FEATURES} ${RESTRICT} || \
+   hasq strip ${RESTRICT}
+then
+	NOSTRIP=1
+	hasq installsources ${FEATURES} || exit 0
+fi
+
+STRIP=${STRIP:-${CHOST}-strip}
+type -P -- ${STRIP} > /dev/null || STRIP=strip
+OBJCOPY=${OBJCOPY:-${CHOST}-objcopy}
+type -P -- ${OBJCOPY} > /dev/null || OBJCOPY=objcopy
+
+export PORTAGE_STRIP_FLAGS=${PORTAGE_STRIP_FLAGS:---strip-unneeded}
+
+banner=1
+
+save_elf_debug() {
+	local x=$1
+	local y="${D}usr/lib/debug/${x:${#D}}.debug"
+
+	if hasq installsources ${FEATURES} && [ -x /usr/bin/debugedit ] ; then
+		local sources_dir=/usr/src/debug/${CATEGORY}/${PF}
+		debugedit -b "${WORKDIR}" -d "${sources_dir}" \
+			-l "${T}"/debug.sources "${x}"
+		if [[ -s ${T}/debug.sources ]] ; then 
+			[[ -d ${D}${sources_dir} ]] || mkdir -p "${D}${sources_dir}"
+			grep -zv '/<built-in>$' "${T}"/debug.sources | \
+				(cd "${WORKDIR}"; LANG=C sort -z -u | \
+				rsync -rtL0 --files-from=- "${WORKDIR}/" "${D}${sources_dir}/" )
+		fi
+	fi
+
+	hasq splitdebug ${FEATURES} || return 0
+	[[ -z "${NOSTRIP}" ]] || return 0
+
+	# dont save debug info twice.
+	[[ ${x:7} == ".debug" ]] && return 0
+
+	mkdir -p $(dirname "${y}")
+	${OBJCOPY} --only-keep-debug "${x}" "${y}"
+	${OBJCOPY} --add-gnu-debuglink="${y}" "${x}"
+	chmod a-x,o-w "${y}"
+
+}
+
+# The existance of the section .symtab tells us that a binary is stripped.
+# We want to log already stripped binaries, as this may be a QA violation.
+# They prevent us from getting the splitdebug data.
+f="$(scanelf -yqRBF '#k%F' -k '!.symtab' "$@")"
+if [[ -n "${f}" ]] ; then
+	vecho -e "\a\n"
+	eqawarn "QA Notice: Pre-stripped files found:"
+	eqawarn "${f}"
+	echo "${f}" > "${T}"/scanelf-already-stripped.log
+fi
+
+# Now we look for unstripped binaries.
+for x in $(scanelf -yqRBF '#k%F' -k '.symtab' "$@") $(for y in "$@"; do find "${y}" -type f -name '*.a' -print ; done); do
+	if [[ ${banner} -eq 1 ]] ; then
+		[[ -z ${NOSTRIP} ]] && vecho "strip: ${STRIP} ${PORTAGE_STRIP_FLAGS}"
+		banner=0
+	fi
+
+	f=$(file "${x}") || continue
+	[[ -z ${f} ]] && continue
+
+	# The noglob funk is to support STRIP_MASK="/*/booga" and to keep
+	#  the for loop from expanding the globs.
+	# The eval echo is to support STRIP_MASK="/*/{booga,bar}" sex.
+	set -o noglob
+	stripitbaby=1
+	for m in $(eval echo ${STRIP_MASK}) ; do
+		[[ ${x} == ${m} ]] && stripitbaby=0 && break
+	done
+	set +o noglob
+
+	if [[ ${f} == *"current ar archive"* ]] ; then
+		vecho "   ${x:${#D}}"
+		[[ -n ${NOSTRIP} ]] && continue
+		[[ ${stripitbaby} -eq 1 ]] && ${STRIP} -g "${x}"
+	fi
+	if [[ ${f} == *"SB executable"* || ${f} == *"SB shared object"* ]] ; then
+		vecho "   ${x:${#D}}"
+		save_elf_debug "${x}"
+		[[ -n ${NOSTRIP} ]] && continue
+		[[ ${stripitbaby} -eq 1 ]] && ${STRIP} ${PORTAGE_STRIP_FLAGS} "${x}"
+	fi
+done
Index: /vendor/portage/current/bin/quickpkg
===================================================================
--- /vendor/portage/current/bin/quickpkg	(revision 3419)
+++ /vendor/portage/current/bin/quickpkg	(revision 3419)
@@ -0,0 +1,170 @@
+#!/bin/bash
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: quickpkg 4570 2006-10-01 23:15:49Z zmedico $
+
+# This script tries to quickly create a Gentoo binary package using the
+# VDB_PATH/category/pkg/*  files
+#
+# Resulting tbz2 file will be created in ${PKGDIR} ...
+# default is /usr/portage/packages/All/
+
+if [ "${UID}" != "0" ] ; then
+	echo "You must run this as root"
+	exit 1
+fi
+
+# We need to ensure a sane umask for the packages that will be created.
+umask 022
+
+eval $(portageq envvar -v NOCOLOR PKGDIR PORTAGE_BIN_PATH PORTAGE_NICENESS \
+	PORTAGE_PYM_PATH PORTAGE_TMPDIR ROOT)
+export PKGDIR PORTAGE_TMPDIR ROOT
+
+[ -n "${PORTAGE_NICENESS}" ] && renice $PORTAGE_NICENESS $$ > /dev/null
+
+# Make sure the xpak module is in PYTHONPATH
+export PYTHONPATH=${PORTAGE_PYM_PATH}
+export PORTAGE_DB=$(portageq vdb_path)
+
+if [ -z "$1" ] || [ $1 == "-h" ] || [ $1 == "--help" ] ; then
+	echo "QUICKPKG ver 1.2"
+	echo "USAGE: quickpkg <list of pkgs>"
+	echo "    a pkg can be of the form:"
+	echo "        - ${PORTAGE_DB}/<CATEGORY>/<PKG-VERSION>/"
+	echo "        - single depend-type atom ..."
+	echo "              if portage can emerge it, quickpkg can make a package"
+	echo "              for exact definitions of depend atoms, see ebuild(5)"
+	echo
+	echo "EXAMPLE:"
+	echo "    quickpkg ${PORTAGE_DB}/net-www/apache-1.3.27-r1"
+	echo "        package up apache, just version 1.3.27-r1"
+	echo "    quickpkg apache"
+	echo "        package up apache, all versions of apache installed"
+	echo "    quickpkg =apache-1.3.27-r1"
+	echo "        package up apache, just version 1.3.27-r1"
+	exit 1
+fi
+
+source "${PORTAGE_BIN_PATH}/isolated-functions.sh"
+case "${NOCOLOR:-false}" in
+	yes|true)
+		unset_colors
+		;;
+	no|false)
+		set_colors
+		;;
+esac
+
+# here we make a package given a little info
+# $1 = package-name w/version
+# $2 = category
+do_pkg() {
+	mkdir -p "${PORTAGE_TMPDIR}/binpkgs" || exit 1
+	chmod 0750 "${PORTAGE_TMPDIR}/binpkgs"
+	MYDIR="${PORTAGE_TMPDIR}/binpkgs/$1"
+	SRCDIR="${PORTAGE_DB}/$2/$1"
+	LOG="${PORTAGE_TMPDIR}/binpkgs/$1-quickpkglog"
+
+	ebegin "Building package for $1"
+	(
+		# clean up temp directory
+		rm -rf "${MYDIR}"
+
+		# get pkg info files
+		mkdir -p "${MYDIR}"/temp
+		cp "${SRCDIR}"/* "${MYDIR}"/temp/
+		[ -d "${PKGDIR}"/All ] ||  mkdir -p "${PKGDIR}"/All
+		local pkg_dest="${PKGDIR}/All/${1}.tbz2"
+		local pkg_tmp="${PKGDIR}/All/${1}.tbz2.$$"
+
+		# create filelist and a basic tbz2
+		gawk '{
+			if ($1 != "dir") {
+				if ($1 == "obj")
+					NF=NF-2
+				else if ($1 == "sym")
+					NF=NF-3
+			}
+			print
+		}' "${SRCDIR}"/CONTENTS | cut -f2- -d" " - | sed -e 's:^/:./:' | \
+		while read f; do
+			[ -d "${ROOT}/${f}" ] && [ -h "${ROOT}/${f}" ] && continue
+			echo "$f"
+		done > "${MYDIR}"/filelist
+		tar vjcf "${pkg_tmp}" -C "${ROOT}" --files-from="${MYDIR}"/filelist --no-recursion
+
+		# join together the basic tbz2 and the pkg info files
+		python -c "import xpak; t=xpak.tbz2('${pkg_tmp}'); t.recompose('${MYDIR}/temp')"
+
+		# move the final binary package to PKGDIR
+		mv -f "${pkg_tmp}" "${pkg_dest}"
+		[ -d "${PKGDIR}/$2" ] || mkdir -p "${PKGDIR}/$2"
+		( cd "${PKGDIR}/$2" && ln -s ../All/$1.tbz2 )
+
+		# cleanup again
+		rm -rf "${MYDIR}"
+	) >& "${LOG}"
+
+	if [ -e "${PKGDIR}/All/$1.tbz2" ] ; then
+		rm -f "${LOG}"
+		PKGSTATS="${PKGSTATS}"$'\n'"$(einfo $1: $(du -h "${PKGDIR}/All/$1.tbz2" | gawk '{print $1}'))"
+		eend 0
+	else
+		cat ${LOG}
+		PKGSTATS="${PKGSTATS}"$'\n'"$(ewarn $1: not created)"
+		eend 1
+	fi
+}
+
+# here we parse the parameters given to use on the cmdline
+export PKGERROR=""
+export PKGSTATS=""
+for x in "$@" ; do
+
+	# they gave us full path
+	if [ -e "${x}"/CONTENTS ] ; then
+		x=$(readlink -f $x)
+		pkg=$(echo ${x} | cut -d/ -f6)
+		cat=$(echo ${x} | cut -d/ -f5)
+		do_pkg "${pkg}" "${cat}"
+
+	# lets figure out what they want
+	else
+		DIRLIST=$(portageq match "${ROOT}" "${x}")
+		if [ -z "${DIRLIST}" ] ; then
+			eerror "Could not find anything to match '${x}'; skipping"
+			export PKGERROR="${PKGERROR} ${x}"
+			continue
+		fi
+
+		for d in ${DIRLIST} ; do
+			pkg=$(echo ${d} | cut -d/ -f2)
+			cat=$(echo ${d} | cut -d/ -f1)
+			if [ -f "${PORTAGE_DB}/${cat}/${pkg}/CONTENTS" ] ; then
+				do_pkg ${pkg} ${cat}
+			elif [ -d "${PORTAGE_DB}/${cat}/${pkg}" ] ; then
+				ewarn "Package '${cat}/${pkg}' was injected; skipping"
+			else
+				eerror "Unhandled case (${cat}/${pkg}) !"
+				eerror "Please file a bug at http://bugs.gentoo.org/"
+				exit 10
+			fi
+		done
+	fi
+
+done
+
+if [ -z "${PKGSTATS}" ] ; then
+	eerror "No packages found"
+	exit 1
+else
+	echo $'\n'"$(einfo Packages now in ${PKGDIR}:)${PKGSTATS}"
+fi
+if [ ! -z "${PKGERROR}" ] ; then
+	ewarn "The following packages could not be found:"
+	ewarn "${PKGERROR}"
+	exit 2
+fi
+
+exit 0
Index: /vendor/portage/current/bin/regenworld
===================================================================
--- /vendor/portage/current/bin/regenworld	(revision 3419)
+++ /vendor/portage/current/bin/regenworld	(revision 3419)
@@ -0,0 +1,95 @@
+#!/usr/bin/python
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: regenworld 5597 2007-01-12 08:19:46Z antarus $
+
+import sys, os
+try:
+	import portage
+except ImportError:
+	from os import path as osp
+	sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
+	import portage
+import re
+
+__candidatematcher__ = re.compile("^[0-9]+: \\*\\*\\* emerge ")
+__noncandidatematcher__ = re.compile(" sync( |$)| clean( |$)| search( |$)|--oneshot|--fetchonly| unmerge( |$)")
+
+def issyspkg(pkgline):
+	return (pkgline[0] == "*")
+
+def iscandidate(logline):
+	return (__candidatematcher__.match(logline) \
+				and not __noncandidatematcher__.search(logline))
+
+def getpkginfo(logline):
+	logline = re.sub("^[0-9]+: \\*\\*\\* emerge ", "", logline)
+	logline = logline.strip()
+	logline = re.sub("(\\S+\\.(ebuild|tbz2))|(--\\S+)|inject ", "", logline)
+	return logline.strip()
+
+__uniqlist__ = []
+def isunwanted(pkgline):
+	if pkgline in ["world", "system", "depclean", "info", "regen", ""]:
+		return False
+	elif pkgline in __uniqlist__:
+		return False
+	elif not re.search("^[a-zA-Z<>=~]", pkgline):
+		return False
+	else:
+		__uniqlist__.append(pkgline)
+		return True
+
+# show a little description if we have arguments
+if len(sys.argv) >= 2 and sys.argv[1] in ["-h", "--help"]:
+	print "This script regenerates the portage world file by checking the portage"
+	print "logfile for all actions that you've done in the past. It ignores any"
+	print "arguments except --help. It is recommended that you make a backup of"
+	print "your existing world file (%s) before using this tool." % portage.WORLD_FILE
+	sys.exit(0)
+
+worldlist = portage.grabfile(os.path.join("/", portage.WORLD_FILE))
+syslist = portage.settings.packages
+syslist = filter(issyspkg, syslist)
+
+logfile = portage.grabfile("/var/log/emerge.log")
+biglist = filter(iscandidate, logfile)
+biglist = map(getpkginfo, biglist)
+tmplist = []
+for l in biglist:
+	tmplist += l.split()
+biglist = filter(isunwanted, tmplist)
+#for p in biglist:
+#	print p
+#sys.exit(0)
+
+# resolving virtuals
+realsyslist = []
+for mykey in syslist:
+	# drop the asterix
+	mykey = mykey[1:]
+	#print "candidate:",mykey
+	mylist=portage.db["/"]["vartree"].dbapi.match(mykey)
+	if mylist:
+		mykey=portage.cpv_getkey(mylist[0])
+		if mykey not in realsyslist:
+			realsyslist.append(mykey)
+
+for mykey in biglist:
+	#print "checking:",mykey
+	try:
+		mylist=portage.db["/"]["vartree"].dbapi.match(mykey)
+	except KeyError:
+		if "--debug" in sys.argv:
+			print "* ignoring broken log entry for %s (likely injected)" % mykey
+	except ValueError, e:
+		print "* %s is an ambigous package name, candidates are:\n%s" % (mykey, e)
+		continue
+	if mylist:
+		#print "mylist:",mylist
+		myfavkey=portage.cpv_getkey(mylist[0])
+		if (myfavkey not in realsyslist) and (myfavkey not in worldlist):
+			print "add to world:",myfavkey
+			worldlist.append(myfavkey)
+
+portage.write_atomic(os.path.join("/", portage.WORLD_FILE), "\n".join(worldlist))
Index: /vendor/portage/current/bin/repoman
===================================================================
--- /vendor/portage/current/bin/repoman	(revision 3419)
+++ /vendor/portage/current/bin/repoman	(revision 3419)
@@ -0,0 +1,1851 @@
+#!/usr/bin/python -O
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: repoman 5603 2007-01-12 09:07:46Z antarus $
+
+# Next to do: dep syntax checking in mask files
+# Then, check to make sure deps are satisfiable (to avoid "can't find match for" problems)
+# that last one is tricky because multiple profiles need to be checked.
+
+import errno, os, shutil, sys
+if not hasattr(__builtins__, "set"):
+	from sets import Set as set
+exename=os.path.basename(sys.argv[0])	
+version="1.2"	
+
+allowed_filename_chars="a-zA-Z0-9._-+:"
+allowed_filename_chars_set = {}
+map(allowed_filename_chars_set.setdefault, map(chr, range(ord('a'), ord('z')+1)))
+map(allowed_filename_chars_set.setdefault, map(chr, range(ord('A'), ord('Z')+1)))
+map(allowed_filename_chars_set.setdefault, map(chr, range(ord('0'), ord('9')+1)))
+map(allowed_filename_chars_set.setdefault, map(chr, map(ord, [".", "-", "_", "+", ":"])))
+
+import signal,re,pickle,tempfile
+
+os.environ["PORTAGE_LEGACY_GLOBALS"] = "false"
+try:
+	import portage
+except ImportError:
+	from os import path as osp
+	sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
+	import portage
+del os.environ["PORTAGE_LEGACY_GLOBALS"]
+
+import portage_checksum
+import portage_const
+import portage_dep
+portage_dep._dep_check_strict = True
+import portage_exception
+import cvstree
+import time
+import codecs
+
+from portage_manifest import Manifest
+from portage_exception import ParseError
+from portage_exec import spawn
+
+from output import bold, darkgreen, darkred, green, nocolor, red, turquoise, yellow
+
+from commands import getstatusoutput
+from fileinput import input
+from grp import getgrnam
+from stat import S_ISDIR, ST_CTIME, ST_GID, ST_MTIME
+
+# A sane umask is needed for files that portage creates.
+os.umask(022)
+repoman_settings = portage.config(local_config=False,
+	config_incrementals=portage_const.INCREMENTALS)
+repoman_settings.lock()
+
+if repoman_settings.get("NOCOLOR", "").lower() in ("yes", "true") or \
+	not sys.stdout.isatty():
+	nocolor()
+
+def warn(txt):
+	print exename+": "+txt
+def err(txt):
+	warn(txt)
+	sys.exit(1)
+
+def err_help(txt):
+	help(exitstatus=-1,helpfulness=0)
+	warn(txt)
+	sys.exit(1)
+
+def exithandler(signum=None,frame=None):
+	sys.stderr.write("\n"+exename+": Interrupted; exiting...\n")
+	sys.exit(1)
+	os.kill(0,signal.SIGKILL)
+signal.signal(signal.SIGINT,exithandler)
+
+shortmodes={"ci":"commit"}
+modeshelp={
+"scan"   : "Scan directory tree for QA issues (default)",
+"fix"    : "Fix simple QA issues (stray digests, missing digests)",
+"full"   : "Scan directory tree for QA issues (full listing)",
+"help"   : "Show this screen",
+"commit" : "Scan directory tree for QA issues; if OK, commit via cvs",
+"last"   : "Remember report from last run",
+"lfull"  : "Remember report from last run (full listing)"
+}
+modes=modeshelp.keys()
+repoman_options={
+"--commitmsg"      : "Adds a commit message via the command line",
+"--commitmsgfile"  : "Adds a commit message from the specified file",
+"--help"           : "Show this screen",
+"--ignore-arches"  : "Ignore arch-specific failures (where arch != host)",
+"--ignore-masked"  : "Ignore masked packages (not allowed with commit mode)",
+"--pretend"        : "Don't commit or fix anything; just show what would be done",
+"--quiet"          : "Be less verbose about extraneous info",
+"--verbose"        : "Displays every package name while checking",
+"--version"        : "Show version info",
+"--xmlparse"       : "Forces the metadata.xml parse check to be carried out"
+}
+repoman_shortoptions={
+"-h" : "--help",
+"-i" : "--ignore-masked",
+"-I" : "--ignore-arches",
+"-m" : "--commitmsg",
+"-M" : "--commitmsgfile",
+"-p" : "--pretend",
+"-q" : "--quiet",
+"-v" : "--verbose",
+"-V" : "--version",
+"-x" : "--xmlparse"
+}
+repoman_shortoptions_rev=dict([(v,k) for (k,v) in repoman_shortoptions.items()])
+options=repoman_options.keys()
+
+qahelp={
+	"CVS/Entries.IO_error":"Attempting to commit, and an IO error was encountered access the Entries file",
+	"digest.partial":"Digest files do not contain all corresponding URI elements",
+	"digest.assumed":"Existing digest must be assumed correct (Package level only)",
+	"digestentry.unused":"Digest/Manifest entry has no matching SRC_URI entry",
+	"digest.fail":"Digest does not match the specified local file",
+	"digest.stray":"Digest files that do not have a corresponding ebuild",
+	"digest.missing":"Digest files that are missing (ebuild exists, digest doesn't)",
+	"digest.disjointed":"Digests not added to cvs when the matching ebuild has been added",
+	"digest.notadded":"Digests that exist but have not been added to cvs",
+	"digest.unmatch":"Digests which are incomplete (please check if your USE/ARCH includes all files)",
+	"ebuild.invalidname":"Ebuild files with a non-parseable or syntactically incorrect name (or using 2.1 versioning extensions)",
+	"ebuild.namenomatch":"Ebuild files that do not have the same name as their parent directory",
+	"changelog.missing":"Missing ChangeLog files",
+	"ebuild.disjointed":"Ebuilds not added to cvs when the matching digest has been added",
+	"ebuild.notadded":"Ebuilds that exist but have not been added to cvs",
+	"changelog.notadded":"ChangeLogs that exist but have not been added to cvs",
+	"filedir.missing":"Package lacks a files directory",
+	"file.executable":"Ebuilds, digests, metadata.xml, Manifest, and ChangeLog do note need the executable bit",
+	"file.size":"Files in the files directory must be under 20k",
+	"file.name":"File/dir name must be composed of only the following chars: %s " % allowed_filename_chars,
+	"file.UTF8":"File is not UTF8 compliant",
+	"KEYWORDS.missing":"Ebuilds that have a missing or empty KEYWORDS variable",
+	"KEYWORDS.stupid":"Ebuilds that use KEYWORDS=-* instead of package.mask", 
+	"LICENSE.missing":"Ebuilds that have a missing or empty LICENSE variable",
+	"DESCRIPTION.missing":"Ebuilds that have a missing or empty DESCRIPTION variable",
+	"SLOT.missing":"Ebuilds that have a missing or empty SLOT variable",
+	"HOMEPAGE.missing":"Ebuilds that have a missing or empty HOMEPAGE variable",
+	"DEPEND.bad":"User-visible ebuilds with bad DEPEND settings (matched against *visible* ebuilds)",
+	"RDEPEND.bad":"User-visible ebuilds with bad RDEPEND settings (matched against *visible* ebuilds)",
+	"PDEPEND.bad":"User-visible ebuilds with bad PDEPEND settings (matched against *visible* ebuilds)",
+	"DEPEND.badmasked":"Masked ebuilds with bad DEPEND settings (matched against *all* ebuilds)",
+	"RDEPEND.badmasked":"Masked ebuilds with RDEPEND settings (matched against *all* ebuilds)",
+	"PDEPEND.badmasked":"Masked ebuilds with PDEPEND settings (matched against *all* ebuilds)",
+	"DEPEND.badindev":"User-visible ebuilds with bad DEPEND settings (matched against *visible* ebuilds) in developing arch",
+	"RDEPEND.badindev":"User-visible ebuilds with bad RDEPEND settings (matched against *visible* ebuilds) in developing arch",
+	"PDEPEND.badindev":"User-visible ebuilds with bad PDEPEND settings (matched against *visible* ebuilds) in developing arch",
+	"DEPEND.badmaskedindev":"Masked ebuilds with bad DEPEND settings (matched against *all* ebuilds) in developing arch",
+	"RDEPEND.badmaskedindev":"Masked ebuilds with RDEPEND settings (matched against *all* ebuilds) in developing arch",
+	"PDEPEND.badmaskedindev":"Masked ebuilds with PDEPEND settings (matched against *all* ebuilds) in developing arch",
+	"DEPEND.syntax":"Syntax error in DEPEND (usually an extra/missing space/parenthesis)",
+	"RDEPEND.syntax":"Syntax error in RDEPEND (usually an extra/missing space/parenthesis)",
+	"PDEPEND.syntax":"Syntax error in PDEPEND (usually an extra/missing space/parenthesis)",
+	"LICENSE.syntax":"Syntax error in LICENSE (usually an extra/missing space/parenthesis)",
+	"PROVIDE.syntax":"Syntax error in PROVIDE (usually an extra/missing space/parenthesis)",
+	"SRC_URI.syntax":"Syntax error in SRC_URI (usually an extra/missing space/parenthesis)",
+	"ebuild.syntax":"Error generating cache entry for ebuild; typically caused by ebuild syntax error",
+	"ebuild.output":"A simple sourcing of the ebuild produces output; this breaks ebuild policy.",
+	"ebuild.nesteddie":"Placing 'die' inside ( ) prints an error, but doesn't stop the ebuild.",
+	"variable.readonly":"Assigning a readonly variable",
+	"LIVEVCS.stable":"This ebuild is a live checkout from a VCS but has stable keywords.",
+	"IUSE.invalid":"This ebuild has a variable in IUSE that is not in the use.desc or use.local.desc file",
+	"LICENSE.invalid":"This ebuild is listing a license that doesnt exist in portages license/ dir.",
+	"KEYWORDS.invalid":"This ebuild contains KEYWORDS that are not listed in profiles/arch.list or for which no valid profile was found",
+	"ebuild.nostable":"There are no ebuilds that are marked as stable for your ARCH",
+	"ebuild.allmasked":"All ebuilds are masked for this package (Package level only)",
+	"ebuild.majorsyn":"This ebuild has a major syntax error that may cause the ebuild to fail partially or fully",
+	"ebuild.minorsyn":"This ebuild has a minor syntax error that contravenes gentoo coding style",
+	"ebuild.badheader":"This ebuild has a malformed header",
+	"metadata.missing":"Missing metadata.xml files",
+	"metadata.bad":"Bad metadata.xml files",
+	"virtual.versioned":"PROVIDE contains virtuals with versions",
+	"virtual.exists":"PROVIDE contains existing package names",
+	"virtual.unavailable":"PROVIDE contains a virtual which contains no profile default",
+	"usage.obsolete":"The ebuild makes use of an obsolete construct"
+}
+
+qacats = qahelp.keys()
+qacats.sort()
+
+qawarnings=[
+"changelog.missing",
+"changelog.notadded",
+"ebuild.notadded",
+"ebuild.nostable",
+"ebuild.allmasked",
+"ebuild.nesteddie",
+"digest.assumed",
+"digest.notadded",
+"digest.disjointed",
+"digest.missing",
+"digestentry.unused",
+"DEPEND.badmasked","RDEPEND.badmasked","PDEPEND.badmasked",
+"DEPEND.badindev","RDEPEND.badindev","PDEPEND.badindev",
+"DEPEND.badmaskedindev","RDEPEND.badmaskedindev","PDEPEND.badmaskedindev",
+"IUSE.invalid",
+"KEYWORDS.stupid",
+"KEYWORDS.missing",
+"ebuild.minorsyn",
+"ebuild.badheader",
+"file.size",
+"metadata.missing",
+"metadata.bad",
+"virtual.versioned",
+"virtual.exists",
+"virtual.unavailable",
+"usage.obsolete",
+"LIVEVCS.stable"
+]
+
+missingvars=["KEYWORDS","LICENSE","DESCRIPTION","HOMEPAGE","SLOT"]
+allvars=portage.auxdbkeys
+commitmessage=None
+commitmessagefile=None
+for x in missingvars:
+	x += ".missing"
+	if x not in qacats:
+		print "* missingvars values need to be added to qahelp ("+x+")"
+		qacats.append(x)
+		qawarnings.append(x)
+
+
+verbose=0
+quiet=0
+
+def show_version():
+	print exename+" "+version
+	sys.exit(0)
+	
+def help(exitstatus=1,helpfulness=1):
+	if quiet:
+		helpfulness=0
+	if helpfulness:
+		print
+		print green(exename+" "+version)
+		print " \"Quality is job zero.\""
+		print " Copyright 1999-2006 Gentoo Foundation"
+		print " Distributed under the terms of the GNU General Public License v2"
+		print
+	print bold(" Usage:"),turquoise(exename),"[",green("options"),"] [",green("mode"),"]"
+	if helpfulness:
+		print bold(" Modes:"),turquoise("scan (default)"),
+		for x in modes[1:]:
+			print "|",turquoise(x),
+		print
+	print
+	print " "+green("Options".ljust(20)+" Description")
+	for x in options:
+		if repoman_shortoptions_rev.has_key(x):
+			shopt=repoman_shortoptions_rev[x]+", "+x
+		else:
+			shopt="    "+x
+		print " "+shopt.ljust(20),repoman_options[x]
+	print
+	print " "+green("Modes".ljust(20)+" Description")
+	for x in modes:
+		print " "+x.ljust(20),modeshelp[x]
+	if helpfulness:
+		print
+		print " "+green("QA keyword".ljust(20)+" Description")
+		for x in qacats:
+			print " "+x.ljust(20),qahelp[x]
+		print
+	if (exitstatus != -1):
+		sys.exit(exitstatus)
+	else:
+		print
+
+def last():
+	try:
+		#Retrieve and unpickle stats and fails from saved files
+		savedf=open('/var/cache/edb/repo.stats','r')
+		stats = pickle.load(savedf)
+		savedf.close()
+		savedf=open('/var/cache/edb/repo.fails','r')
+		fails = pickle.load(savedf)
+		savedf.close()
+	except SystemExit, e:
+		raise  # Need to propogate this
+	except:
+		err("Error retrieving last repoman run data; exiting.")
+
+	#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
+
+	print
+	print green("RepoMan remembers...")
+	print
+	for x in qacats:
+		if stats[x]:
+			dowarn=1
+			if x not in qawarnings:
+				dofail=1
+		else:
+			continue
+		print "  "+ x.ljust(20),
+		if stats[x]==0:
+			print green(`stats[x]`)
+			continue
+		elif x in qawarnings:
+			print yellow(`stats[x]`)
+		else:
+			print red(`stats[x]`)
+		if mymode!="lfull":
+			if stats[x]<12:
+				for y in fails[x]:
+					print "   "+y
+			else:
+				dofull=1
+		else:
+			for y in fails[x]:
+				print "   "+y
+	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(1)
+
+mymode=None
+myoptions=[]
+if len(sys.argv)>1:
+	x=1
+	while x < len(sys.argv):
+		if sys.argv[x] in shortmodes.keys():
+			sys.argv[x]=shortmodes[sys.argv[x]]
+		elif sys.argv[x] in repoman_shortoptions.keys():
+			sys.argv[x] = repoman_shortoptions[sys.argv[x]]
+		if sys.argv[x] in modes:
+			if mymode is None:
+				mymode=sys.argv[x]
+			else:
+				err("Please specify either \""+mymode+"\" or \""+sys.argv[x]+"\", but not both.")
+		elif sys.argv[x] in options:
+			optionx=sys.argv[x]
+			if (optionx=="--commitmsg") and (len(sys.argv)>=(x+1)):
+				commitmessage=sys.argv[x+1]
+				x=x+1
+			elif (optionx=="--commitmsgfile") and (len(sys.argv)>=(x+1)):
+				commitmessagefile=sys.argv[x+1]
+				x=x+1
+			elif (optionx=="--verbose"):
+				verbose+=1
+			elif (optionx=="--quiet"):
+				quiet+=1
+			elif optionx not in myoptions:
+				myoptions.append(optionx)
+		else:
+			err_help("\""+sys.argv[x]+"\" is not a valid mode or option.")
+		x=x+1
+if mymode is None:
+	mymode="scan"
+if mymode=="help" or ("--help" in myoptions):
+	help(exitstatus=0)
+if ("--version" in myoptions):
+	show_version()
+if mymode=="last" or (mymode=="lfull"):
+	last()
+if mymode == "commit":
+	while "--ignore-masked" in myoptions:
+		myoptions.remove("--ignore-masked")
+
+from portage import normalize_path
+isCvs=False
+myreporoot=None
+if os.path.isdir("CVS"):
+	isCvs = True
+
+if mymode == "commit" and \
+	not isCvs and \
+	"--pretend" not in myoptions:
+	print
+	print darkgreen("Not in a CVS repository; enabling pretend mode.")
+	myoptions.append("--pretend");
+
+
+def have_profile_dir(path, maxdepth=3):
+	while path != "/" and maxdepth:
+		if os.path.exists(path + "/profiles/package.mask"):
+			return normalize_path(path)
+		path = normalize_path(path + "/..")
+		maxdepth -= 1
+
+portdir=None
+portdir_overlay=None
+mydir=os.getcwd()
+if "PWD" in os.environ and os.environ["PWD"] != mydir and \
+	os.path.realpath(os.environ["PWD"]) == mydir:
+	# getcwd() returns the canonical path but that makes it hard for repoman to
+	# orient itself if the user has symlinks in their portage tree structure.
+	# We use os.environ["PWD"], if available, to get the non-canonical path of
+	# the current working directory (from the shell).
+	mydir = os.environ["PWD"]
+mydir = normalize_path(mydir)
+if mydir[-1] != "/":
+	mydir += "/"
+
+for overlay in repoman_settings["PORTDIR_OVERLAY"].split():
+	if overlay[-1] != "/":
+		overlay += "/"
+	if mydir.startswith(overlay):
+		portdir_overlay = overlay
+		subdir = mydir[len(overlay):]
+		if subdir and subdir[-1] != "/":
+			subdir += "/"
+		if have_profile_dir(mydir, subdir.count("/")):
+			portdir = portdir_overlay
+		break
+
+if not portdir_overlay:
+	if (repoman_settings["PORTDIR"] + os.path.sep).startswith(mydir):
+		portdir_overlay = repoman_settings["PORTDIR"]
+	else:
+		portdir_overlay = have_profile_dir(mydir)
+	portdir = portdir_overlay
+
+if not portdir_overlay:
+	sys.stderr.write("Repoman is unable to determine PORTDIR or PORTDIR_OVERLAY from" + \
+		" the current\nworking directory.\n")
+	sys.exit(1)
+
+if not portdir:
+	portdir = repoman_settings["PORTDIR"]
+
+portdir = normalize_path(portdir)
+portdir_overlay = normalize_path(portdir_overlay)
+
+os.environ["PORTDIR"] = portdir
+if portdir_overlay != portdir:
+	os.environ["PORTDIR_OVERLAY"] = portdir_overlay
+else:
+	os.environ["PORTDIR_OVERLAY"] = ""
+
+if quiet < 2:
+	print "\nSetting paths:"
+	print "PORTDIR = \""+os.environ["PORTDIR"]+"\""
+	print "PORTDIR_OVERLAY = \""+os.environ["PORTDIR_OVERLAY"]+"\""
+
+# Now that PORTDIR_OVERLAY is properly overridden, create the portdb.
+repoman_settings = portage.config(local_config=False,
+	config_incrementals=portage_const.INCREMENTALS)
+trees = portage.create_trees()
+trees["/"]["porttree"].settings = repoman_settings
+portdb = trees["/"]["porttree"].dbapi
+portdb.mysettings = repoman_settings
+# dep_zapdeps looks at the vardbapi, but it shouldn't for repoman.
+del trees["/"]["vartree"]
+
+if not myreporoot:
+	myreporoot = os.path.basename(portdir_overlay)
+	myreporoot += mydir[len(portdir_overlay):-1]
+
+reposplit=myreporoot.split("/")
+repolevel=len(reposplit)
+
+# check if it's in $PORTDIR/$CATEGORY/$PN , otherwise bail if commiting.
+# Reason for this is if they're trying to commit in just $FILESDIR/*, the Manifest needs updating.
+# this check ensure that repoman knows where it is, and the manifest recommit is at least possible.
+if mymode == "commit" and repolevel not in [1,2,3]:
+	print red("***")+" Commit attempts *must* be from within a cvs co, category, or package directory."
+	print red("***")+" Attempting to commit from a packages files directory will be blocked for instance."
+	print red("***")+" This is intended behaviour, to ensure the manifest is recommited for a package."
+	print red("***")
+	err("Unable to identify level we're commiting from for %s" % '/'.join(reposplit))
+
+startdir = normalize_path(mydir)
+repodir = startdir
+for x in range(0,repolevel-1):
+	repodir = os.path.dirname(repodir)
+
+def caterror(mycat):
+	err(mycat+" is not an official category.  Skipping QA checks in this directory.\nPlease ensure that you add "+catdir+" to "+repodir+"/profiles/categories\nif it is a new category.")
+if "--pretend" in myoptions:
+	print green("\nRepoMan does a once-over of the neighborhood...")
+elif quiet < 1:
+	print green("\nRepoMan scours the neighborhood...")
+
+def parse_use_local_desc(mylines, usedict=None):
+	"""returns a dict of the form {cpv:set(flags)}"""
+	if usedict is None:
+		usedict = {}
+	lineno = 0
+	for l in mylines:
+		lineno += 1
+		if not l or l.startswith("#"):
+			continue
+		mysplit = l.split(None, 1)
+		if not mysplit:
+			continue
+		mysplit = mysplit[0].split(":")
+		if len(mysplit) != 2:
+			raise ParseError("line %d: Malformed input: '%s'" % \
+				(lineno, l.rstrip("\n")))
+		usedict.setdefault(mysplit[0], set())
+		usedict[mysplit[0]].add(mysplit[1])
+	return usedict
+
+# retreive local USE list
+luselist={}
+try:
+	f = open(os.path.join(portdir, "profiles", "use.local.desc"))
+	parse_use_local_desc(f, luselist)
+	f.close()
+except (IOError, OSError, ParseError), e:
+	print >> sys.stderr, str(e)
+	err("Couldn't read from use.local.desc")
+
+if portdir_overlay != portdir:
+	filename = os.path.join(portdir_overlay, "profiles", "use.local.desc")
+	if os.path.exists(filename):
+		try:
+			f = open(filename)
+			parse_use_local_desc(f, luselist)
+			f.close()
+		except (IOError, OSError, ParseError), e:
+			print >> sys.stderr, str(e)
+			err("Couldn't read from '%s'" % filename)
+	del filename
+
+# setup a uselist from portage
+uselist=[]
+try:
+	uselist=portage.grabfile(portdir+"/profiles/use.desc")
+	for l in range(0,len(uselist)):
+		uselist[l]=uselist[l].split()[0]
+	for var in repoman_settings["USE_EXPAND"].split():
+		vardescs = portage.grabfile(portdir+"/profiles/desc/"+var.lower()+".desc")
+		for l in range(0, len(vardescs)):
+			uselist.append(var.lower() + "_" + vardescs[l].split()[0])
+except SystemExit, e:
+	raise  # Need to propogate this
+except:
+	err("Couldn't read USE flags from use.desc")
+
+# retrieve a list of current licenses in portage
+liclist = set(portage.listdir(os.path.join(portdir, "licenses")))
+if not liclist:
+	err("Couldn't find licenses?")
+if portdir_overlay != portdir:
+	liclist.update(portage.listdir(os.path.join(portdir_overlay, "licenses")))
+
+# retrieve list of offical keywords
+kwlist = set(portage.grabfile(os.path.join(portdir, "profiles", "arch.list")))
+if not kwlist:
+	err("Couldn't read KEYWORDS from arch.list")
+
+manifest1_compat = not os.path.exists(
+	os.path.join(portdir, "manifest1_obsolete"))
+if portdir_overlay != portdir:
+	kwlist.update(portage.grabfile(
+		os.path.join(portdir_overlay, "profiles", "arch.list")))
+	manifest1_compat = not os.path.exists(
+		os.path.join(portdir_overlay, "manifest1_obsolete"))
+
+scanlist=[]
+if repolevel==2:
+	#we are inside a category directory
+	catdir=reposplit[-1]
+	if catdir not in repoman_settings.categories:
+		caterror(catdir)
+	mydirlist=os.listdir(startdir)
+	for x in mydirlist:
+		if x == "CVS" or x.startswith("."):
+			continue
+		if os.path.isdir(startdir+"/"+x):
+			scanlist.append(catdir+"/"+x)
+elif repolevel==1:
+	for x in repoman_settings.categories:
+		if not os.path.isdir(startdir+"/"+x):
+			continue
+		for y in os.listdir(startdir+"/"+x):
+			if y == "CVS" or y.startswith("."):
+				continue
+			if os.path.isdir(startdir+"/"+x+"/"+y):
+				scanlist.append(x+"/"+y)
+elif repolevel==3:
+	catdir = reposplit[-2]
+	if catdir not in repoman_settings.categories:
+		caterror(catdir)
+	scanlist.append(catdir+"/"+reposplit[-1])
+
+profiles={}
+descfile=portdir+"/profiles/profiles.desc"
+if os.path.exists(descfile):
+	for x in portage.grabfile(descfile):
+		if x[0]=="#":
+			continue
+		arch=x.split()
+		if len(arch)!=3:
+			print "wrong format: \""+red(x)+"\" in "+descfile
+			continue
+		if not os.path.isdir(portdir+"/profiles/"+arch[1]):
+			print "Invalid "+arch[2]+" profile ("+arch[1]+") for arch "+arch[0]
+			continue
+		if profiles.has_key(arch[0]):
+			profiles[arch[0]]+= [[arch[1], arch[2]]]
+		else:
+			profiles[arch[0]] = [[arch[1], arch[2]]]
+
+	for x in repoman_settings.archlist():
+		if x[0] == "~":
+			continue
+		if not profiles.has_key(x):
+			print red("\""+x+"\" doesn't have a valid profile listed in profiles.desc.")
+			print red("You need to either \"cvs update\" your profiles dir or follow this")
+			print red("up with the "+x+" team.")
+			print
+else:
+	print red("profiles.desc does not exist: "+descfile)
+	print red("You need to do \"cvs update\" in profiles dir.")
+	print
+	sys.exit(1)
+
+
+stats={}
+fails={}
+
+for x in qacats:
+	stats[x]=0
+	fails[x]=[]
+xmllint_capable = False
+if getstatusoutput('which xmllint')[0] != 0:
+	print red("!!! xmllint not found. Can't check metadata.xml.\n")
+	if "--xmlparse" in myoptions or repolevel==3:
+		print red("!!!")+" sorry, xmllint is needed.  failing\n"
+		sys.exit(1)
+else:
+	#hardcoded paths/urls suck. :-/
+	must_fetch=1
+	backup_exists=0
+	try:
+		# if it's been over a week since fetching (or the system clock is fscked), grab an updated copy of metadata.dtd 
+		# clock is fscked or it's been a week. time to grab a new one.
+		ct=os.stat(portage.CACHE_PATH + '/metadata.dtd')[ST_CTIME]
+		if abs(time.time() - ct) > (60*60*24*7):
+			# don't trap the exception, we're watching for errno 2 (file not found), anything else is a bug.
+			backup_exists=1
+		else:
+			must_fetch=0
+
+	except (OSError,IOError), e:
+		if e.errno != 2:
+			print red("!!!")+" caught exception '%s' for %s/metadata.dtd, bailing" % (str(e), portage.CACHE_PATH)
+			sys.exit(1)
+
+	if must_fetch:
+		print 
+		print green("***")+" the local copy of metadata.dtd needs to be refetched, doing that now"
+		print
+		try:
+			if os.path.exists(repoman_settings["DISTDIR"]+'/metadata.dtd'):
+				os.remove(repoman_settings["DISTDIR"]+'/metadata.dtd')
+			val=portage.fetch(['http://www.gentoo.org/dtd/metadata.dtd'],repoman_settings,fetchonly=0, \
+				try_mirrors=0)
+			if val:
+				if backup_exists:
+					os.remove(portage.CACHE_PATH+'/metadata.dtd')
+				shutil.copy(repoman_settings["DISTDIR"]+'/metadata.dtd',portage.CACHE_PATH+'/metadata.dtd')
+				os.chown(portage.CACHE_PATH+'/metadata.dtd',os.getuid(),portage.portage_gid)
+				os.chmod(portage.CACHE_PATH+'/metadata.dtd',0664)
+
+
+		except SystemExit, e:
+			raise  # Need to propogate this
+		except Exception,e:
+			print
+			print red("!!!")+" attempting to fetch 'http://www.gentoo.org/dtd/metadata.dtd', caught"
+			print red("!!!")+" exception '%s' though." % str(e)
+			val=0
+		if not val:
+			print red("!!!")+" fetching new metadata.dtd failed, aborting"
+			sys.exit(1)
+	#this can be problematic if xmllint changes their output
+	xmllint_capable=True
+
+
+def x11_deprecation_check(depstr):
+	if depstr.find("virtual/x11") == -1:
+		return False
+	depsplit = depstr.split()
+	ok_stack = []
+	ok = False
+	for token in depsplit:
+		if token == "(":
+			ok_stack.append(ok)
+			ok = False
+		elif token == ")":
+			ok = ok_stack.pop()
+		elif token == "||":
+			ok = True
+		else:
+			ok = False
+			if token.find("virtual/x11") != -1 and (not ok_stack or not ok_stack[-1]):
+				return True
+	return False
+
+
+arch_caches={}
+arch_xmatch_caches = {}
+for x in scanlist:
+	#ebuilds and digests added to cvs respectively.
+	if verbose:
+		print "checking package " + x
+	eadded=[]
+	dadded=[]
+	catdir,pkgdir=x.split("/")
+	checkdir=repodir+"/"+x
+	checkdirlist=os.listdir(checkdir)
+	ebuildlist=[]
+	for y in checkdirlist:
+		if y[-7:]==".ebuild":
+			ebuildlist.append(y[:-7])
+		if y in ["Manifest","ChangeLog","metadata.xml"]:
+			if os.stat(checkdir+"/"+y)[0] & 0x0248:
+				stats["file.executable"] += 1
+				fails["file.executable"].append(checkdir+"/"+y)
+	digestlist=[]
+
+	for y in checkdirlist:
+		for c in y.strip(os.path.sep):
+			if c not in allowed_filename_chars_set:
+				stats["file.name"] += 1
+				fails["file.name"].append("%s/%s: char '%s'" % (checkdir, y, c))
+				break
+
+		if not (y in ("ChangeLog", "metadata.xml") or y.endswith(".ebuild")):
+			continue
+		try:
+			line = 1
+			for l in codecs.open(checkdir+"/"+y, "r", "utf8"):
+				line +=1
+		except UnicodeDecodeError, ue:
+			stats["file.UTF8"] += 1
+			s = ue.object[:ue.start]
+			l2 = s.count("\n")
+			line += l2
+			if l2 != 0:
+				s = s[s.rfind("\n") + 1:]
+			fails["file.UTF8"].append("%s/%s: line %i, just after: '%s'" % (checkdir, y, line, s))
+
+	if isCvs:
+		try:
+			mystat=os.stat(checkdir+"/files")[0]
+			if len(ebuildlist) and not S_ISDIR(mystat):
+				raise Exception
+		except SystemExit, e:
+			raise  # Need to propogate this
+		except:
+			stats["filedir.missing"] += 1
+			fails["filedir.missing"].append(checkdir)
+			continue
+		try:
+			myf=open(checkdir+"/CVS/Entries","r")
+			myl=myf.readlines()
+			for l in myl:
+				if l[0]!="/":
+					continue
+				splitl=l[1:].split("/")
+				if not len(splitl):
+					continue
+				if splitl[0][-7:]==".ebuild":
+					eadded.append(splitl[0][:-7])
+		except IOError:
+			if mymode=="commit":
+				stats["CVS/Entries.IO_error"] += 1
+				fails["CVS/Entries.IO_error"].append(checkdir+"/CVS/Entries")
+			continue
+
+		try:
+			myf=open(checkdir+"/files/CVS/Entries","r")
+			myl=myf.readlines()
+			for l in myl:
+				if l[0]!="/":
+					continue
+				splitl=l[1:].split("/")
+				if not len(splitl):
+					continue
+				if splitl[0][:7]=="digest-":
+					dadded.append(splitl[0][7:])
+		except IOError:
+			if mymode=="commit":
+				stats["CVS/Entries.IO_error"] += 1
+				fails["CVS/Entries.IO_error"].append(checkdir+"/files/CVS/Entries")
+			continue
+
+	if mymode in ("fix", "commit") and \
+		"--pretend" not in myoptions:
+		repoman_settings["O"] = checkdir
+		if not portage.digestgen([], repoman_settings, myportdb=portdb):
+			print "Unable to generate manifest."
+			sys.exit(1)
+
+	mf = Manifest(checkdir, repoman_settings["DISTDIR"])
+	mydigests=mf.getTypeDigests("DIST")
+
+	fetchlist_dict = portage.FetchlistDict(checkdir, repoman_settings, portdb)
+	myfiles_all = []
+	for mykey in fetchlist_dict:
+		try:
+			myfiles_all.extend(fetchlist_dict[mykey])
+		except portage_exception.InvalidDependString, e:
+			stats["SRC_URI.syntax"] = stats["SRC_URI.syntax"] + 1
+			fails["SRC_URI.syntax"].append(mykey+".ebuild SRC_URI: "+str(e))
+	del fetchlist_dict
+	myfiles_all = set(myfiles_all)
+	for entry in mydigests:
+		if entry not in myfiles_all:
+			stats["digestentry.unused"] += 1
+			fails["digestentry.unused"].append(checkdir+"::"+entry)
+	del myfiles_all
+
+	if os.path.exists(checkdir+"/files"):
+		filesdirlist=os.listdir(checkdir+"/files")
+		if manifest1_compat:
+			for y in filesdirlist:
+				if not y.startswith("digest-"):
+					continue
+				if y[7:] not in dadded:
+					#digest not added to cvs
+					stats["digest.notadded"]=stats["digest.notadded"]+1
+					fails["digest.notadded"].append(x+"/files/"+y)
+					if y[7:] in eadded:
+						stats["digest.disjointed"]=stats["digest.disjointed"]+1
+						fails["digest.disjointed"].append(x+"/files/"+y)
+						
+				if os.stat(checkdir+"/files/"+y)[0] & 0x0248:
+					stats["file.executable"] += 1
+					fails["file.executable"].append(x+"/files/"+y)
+				
+				mykey = catdir + "/" + y[7:]
+				if y[7:] not in ebuildlist:
+					#stray digest
+					if mymode=="fix":
+						if "--pretend" in myoptions:
+							print "(cd "+repodir+"/"+x+"/files; cvs rm -f "+y+")"
+						else:
+							os.system("(cd "+repodir+"/"+x+"/files; cvs rm -f "+y+")")
+					else:
+						stats["digest.stray"]=stats["digest.stray"]+1
+						fails["digest.stray"].append(x+"/files/"+y)
+				else:
+					# We have an ebuild
+					try:
+						myuris, myfiles = portdb.getfetchlist(mykey, all=True)
+					except portage_exception.InvalidDependString, e:
+						# Already handled above.
+						continue
+
+					uri_dict = {}
+					for myu in myuris:
+						myubn = os.path.basename(myu)
+						if myubn not in uri_dict:
+							uri_dict[myubn]  = [myu]
+						else:
+							uri_dict[myubn] += [myu]
+
+					for myf in uri_dict:
+						myff = repoman_settings["DISTDIR"] + "/" + myf
+						if not mydigests.has_key(myf):
+							uri_settings = portage.config(clone=repoman_settings)
+							if mymode == "fix":
+								if not portage.fetch(uri_dict[myf], uri_settings):
+									stats["digest.unmatch"] += 1
+									fails["digest.unmatch"].append(y+"::"+myf)
+								else:
+									eb_name = portdb.findname2(mykey)[0]
+									portage.doebuild(eb_name, "digest", "/",
+										uri_settings, tree="porttree",
+										mydbapi=portdb)
+							else:
+								stats["digest.partial"] += 1
+								fails["digest.partial"].append(y+"::"+myf)
+						elif "assume-digests" not in repoman_settings.features:
+							if os.path.exists(myff):
+								if not portage_checksum.verify_all(myff, mydigests[myf]):
+									stats["digest.fail"] += 1
+									fails["digest.fail"].append(y+"::"+myf)
+							elif repolevel == 3:
+								stats["digest.assumed"] += 1
+								fails["digest.assumed"].append(y+"::"+myf)
+
+		# recurse through files directory
+		# use filesdirlist as a stack, appending directories as needed so people can't hide > 20k files in a subdirectory.
+		while filesdirlist:
+			y = filesdirlist.pop(0)
+			try:
+				mystat = os.stat(checkdir+"/files/"+y)
+			except OSError, oe:
+				if oe.errno == 2:
+					# don't worry about it.  it likely was removed via fix above.
+					continue
+				else:
+					raise oe
+			if S_ISDIR(mystat.st_mode):
+				if y == "CVS":
+					continue
+				for z in os.listdir(checkdir+"/files/"+y):
+					if z == "CVS":
+						continue
+					filesdirlist.append(y+"/"+z)
+			# current policy is no files over 20k, this is the check.
+			elif mystat.st_size > 20480:
+				stats["file.size"] += 1
+				fails["file.size"].append("("+ str(mystat.st_size/1024) + "K) "+x+"/files/"+y)
+
+			for c in os.path.basename(y.rstrip(os.path.sep)):
+				if c not in allowed_filename_chars_set:
+					stats["file.name"] += 1
+					fails["file.name"].append("%s/files/%s: char '%s'" % (checkdir, y, c))
+					break
+
+	del mydigests
+
+	if "ChangeLog" not in checkdirlist:
+		stats["changelog.missing"]+=1
+		fails["changelog.missing"].append(x+"/ChangeLog")
+	
+	#metadata.xml file check
+	if "metadata.xml" not in checkdirlist:
+		stats["metadata.missing"]+=1
+		fails["metadata.missing"].append(x+"/metadata.xml")
+	#metadata.xml parse check
+	else:
+		#Only carry out if in package directory or check forced
+		if xmllint_capable:
+			st=getstatusoutput("xmllint --nonet --noout --dtdvalid %s/metadata.dtd %s/metadata.xml" % (portage.CACHE_PATH, checkdir))
+			if st[0] != 0:
+				for z in st[1].split("\n"):
+					print red("!!! ")+z
+				stats["metadata.bad"]+=1
+				fails["metadata.bad"].append(x+"/metadata.xml")
+
+	allmasked = True
+
+	for y in ebuildlist:
+		if os.stat(checkdir+"/"+y+".ebuild")[0] & 0x0248:
+			stats["file.executable"] += 1
+			fails["file.executable"].append(x+"/"+y+".ebuild")
+		if y not in eadded:
+			#ebuild not added to cvs
+			stats["ebuild.notadded"]=stats["ebuild.notadded"]+1
+			fails["ebuild.notadded"].append(x+"/"+y+".ebuild")
+			if y in dadded:
+				stats["ebuild.disjointed"]=stats["ebuild.disjointed"]+1
+				fails["ebuild.disjointed"].append(x+"/"+y+".ebuild")
+		if manifest1_compat and \
+			not os.path.exists(os.path.join(checkdir, "files", "digest-"+y)):
+			if mymode=="fix":
+				if "--pretend" in myoptions:
+					print "You will need to run:"
+					print "  /usr/bin/ebuild "+repodir+"/"+x+"/"+y+".ebuild digest"
+				else:
+					retval=os.system("/usr/bin/ebuild "+repodir+"/"+x+"/"+y+".ebuild digest")
+					if retval:
+						print "!!! Exiting on ebuild digest (shell) error code:",retval
+						sys.exit(retval)
+			else:
+				stats["digest.missing"]=stats["digest.missing"]+1
+				fails["digest.missing"].append(x+"/files/digest-"+y)
+		myesplit=portage.pkgsplit(y)
+		if myesplit is None or myesplit[0] != x.split("/")[-1]:
+			stats["ebuild.invalidname"]=stats["ebuild.invalidname"]+1
+			fails["ebuild.invalidname"].append(x+"/"+y+".ebuild")
+			continue
+		elif myesplit[0]!=pkgdir:
+			print pkgdir,myesplit[0]
+			stats["ebuild.namenomatch"]=stats["ebuild.namenomatch"]+1
+			fails["ebuild.namenomatch"].append(x+"/"+y+".ebuild")
+			continue
+		try:
+			myaux = dict(
+				zip(allvars, portdb.aux_get(os.path.join(catdir, y), allvars)))
+		except KeyError:
+			stats["ebuild.syntax"]=stats["ebuild.syntax"]+1
+			fails["ebuild.syntax"].append(x+"/"+y+".ebuild")
+			continue
+		except IOError:
+			stats["ebuild.output"]=stats["ebuild.output"]+1
+			fails["ebuild.output"].append(x+"/"+y+".ebuild")
+			continue
+
+		# Test for negative logic and bad words in the RESTRICT var.
+		#for x in myaux[allvars.index("RESTRICT")].split():
+		#	if x.startswith("no"):
+		#		print "Bad RESTRICT value: %s" % x
+		try:
+			myaux["PROVIDE"] = portage_dep.use_reduce(
+				portage_dep.paren_reduce(myaux["PROVIDE"]), matchall=1)
+		except portage_exception.InvalidDependString, e:
+			stats["PROVIDE.syntax"] = stats["PROVIDE.syntax"] + 1
+			fails["PROVIDE.syntax"].append(mykey+".ebuild PROVIDE: "+str(e))
+			del e
+			continue
+		myaux["PROVIDE"] = " ".join(portage.flatten(myaux["PROVIDE"]))
+		for myprovide in myaux["PROVIDE"].split():
+			prov_cp = portage.dep_getkey(myprovide)
+			if prov_cp != myprovide:
+				stats["virtual.versioned"]+=1
+				fails["virtual.versioned"].append(x+"/"+y+".ebuild: "+myprovide)
+			prov_pkg = portage.dep_getkey(
+				portage.best(portdb.xmatch("match-all", prov_cp)))
+			if prov_cp == prov_pkg:
+				stats["virtual.exists"]+=1
+				fails["virtual.exists"].append(x+"/"+y+".ebuild: "+prov_cp)
+
+		for pos in range(0,len(missingvars)):
+			if not myaux[missingvars[pos]]:
+				myqakey=missingvars[pos]+".missing"
+				stats[myqakey]=stats[myqakey]+1
+				fails[myqakey].append(x+"/"+y+".ebuild")
+
+		# KEYWORDS="-*" is a stupid replacement for package.mask and screws general KEYWORDS semantics
+		if "-*" in myaux["KEYWORDS"].split():
+			haskeyword = False
+			for kw in myaux["KEYWORDS"].split():
+				if kw[0] == "~":
+					kw = kw[1:]
+				if kw in kwlist:
+					haskeyword = True
+			if not haskeyword:
+				stats["KEYWORDS.stupid"] += 1
+				fails["KEYWORDS.stupid"].append(x+"/"+y+".ebuild")
+
+		"""
+		Ebuilds that inherit a "Live" eclasss (darcs,subversion,git,cvs,etc..) should
+		not be allowed to be marked stable
+		"""
+		if set(["darcs","cvs","subversion","git"]).intersection(
+			myaux["INHERITED"].split()):
+			bad_stable_keywords = []
+			for keyword in myaux["KEYWORDS"].split():
+				if not keyword.startswith("~") and \
+					not keyword.startswith("-"):
+					bad_stable_keywords.append(keyword)
+				del keyword
+			if bad_stable_keywords:
+				stats["LIVEVCS.stable"] += 1
+				fails["LIVEVCS.stable"].append(
+					x + "/" + y + ".ebuild with stable keywords:%s " % \
+						bad_stable_keywords)
+			del bad_stable_keywords
+
+		if "--ignore-arches" in myoptions:
+			arches = [[repoman_settings["ARCH"], repoman_settings["ARCH"],
+				repoman_settings["ACCEPT_KEYWORDS"].split()]]
+		else:
+			arches=[]
+			for keyword in myaux["KEYWORDS"].split():
+				if (keyword[0]=="-"):
+					continue
+				elif (keyword[0]=="~"):
+					arches.append([keyword, keyword[1:], [keyword[1:], keyword]])
+				else:
+					arches.append([keyword, keyword, [keyword]])
+					allmasked = False
+
+		baddepsyntax = False
+		badlicsyntax = False
+		badprovsyntax = False
+		catpkg = catdir+"/"+y
+		myiuse = set(repoman_settings.archlist())
+		for myflag in myaux["IUSE"].split():
+			if myflag.startswith("+"):
+				myflag = myflag[1:]
+			myiuse.add(myflag)
+
+		operator_tokens = set(["||", "(", ")"])
+		type_list, badsyntax = [], []
+		for mytype in ("DEPEND", "RDEPEND", "PDEPEND", "LICENSE", "PROVIDE"):
+			mydepstr = myaux[mytype]
+			
+			if mydepstr.find(" ?") != -1:
+				badsyntax.append("'?' preceded by space")
+
+			try:
+				# Missing closing parenthesis will result in a ValueError
+				mydeplist = portage_dep.paren_reduce(mydepstr)
+				# Missing opening parenthesis will result in a final "" element
+				if "" in mydeplist or "(" in mydeplist:
+					raise ValueError
+			except ValueError:
+				badsyntax.append("parenthesis mismatch")
+				mydeplist = []
+
+			try:
+				portage_dep.use_reduce(mydeplist, excludeall=myiuse)
+			except portage_exception.InvalidDependString, e:
+				badsyntax.append(str(e))
+
+			for token in operator_tokens:
+				if mydepstr.startswith(token+" "):
+					myteststr = mydepstr[len(token):]
+				else:
+					myteststr = mydepstr
+				if myteststr.endswith(" "+token):
+					myteststr = myteststr[:-len(token)]
+				while myteststr.find(" "+token+" ") != -1:
+					myteststr = " ".join(myteststr.split(" "+token+" ", 1))
+				if myteststr.find(token) != -1:
+					badsyntax.append("'%s' not separated by space" % (token))
+
+
+			if mytype in ("DEPEND", "RDEPEND", "PDEPEND"):
+				for token in mydepstr.split():
+					if token in operator_tokens or \
+						token.endswith("?"):
+						continue
+					if not portage.isvalidatom(token, allow_blockers=True) or \
+						":" in token and myaux["EAPI"] == "0":
+						badsyntax.append("'%s' not a valid atom" % token)
+
+			type_list.extend([mytype] * (len(badsyntax) - len(type_list)))
+
+		for m,b in zip(type_list, badsyntax):
+			stats[m+".syntax"] += 1
+			fails[m+".syntax"].append(catpkg+".ebuild "+m+": "+b)
+
+		badlicsyntax = len(filter(lambda x:x=="LICENSE", type_list))
+		badprovsyntax = len(filter(lambda x:x=="PROVIDE", type_list))
+		baddepsyntax = len(type_list) != badlicsyntax + badprovsyntax 
+		badlicsyntax = badlicsyntax > 0
+		badprovsyntax = badprovsyntax > 0
+
+		if not baddepsyntax:
+			if x11_deprecation_check(" ".join([myaux["DEPEND"], myaux["RDEPEND"], myaux["PDEPEND"]])):
+				stats["usage.obsolete"] += 1
+				fails["usage.obsolete"].append("%s/%s.ebuild: not migrated to modular X" % (x, y))
+
+		for keyword,arch,groups in arches:
+
+			if not profiles.has_key(arch):
+				# A missing profile will create an error further down
+				# during the KEYWORDS verification.
+				continue
+				
+			for prof in profiles[arch]:
+
+				profdir = portdir+"/profiles/"+prof[0]
+	
+				if prof[0] in arch_caches:
+					dep_settings = arch_caches[prof[0]]
+				else:
+					dep_settings = portage.config(
+						config_profile_path=profdir,
+						config_incrementals=portage_const.INCREMENTALS,
+						local_config=False)
+					arch_caches[prof[0]] = dep_settings
+					while True:
+						try:
+							# Protect ACCEPT_KEYWORDS from config.regenerate()
+							# (just in case)
+							dep_settings.incrementals.remove("ACCEPT_KEYWORDS")
+						except ValueError:
+							break
+
+				xmatch_cache_key = (prof[0], tuple(groups))
+				xcache = arch_xmatch_caches.get(xmatch_cache_key)
+				if xcache is None:
+					portdb.melt()
+					portdb.freeze()
+					xcache = portdb.xcache
+					arch_xmatch_caches[xmatch_cache_key] = xcache
+
+				trees["/"]["porttree"].settings = dep_settings
+				portdb.mysettings = dep_settings
+				portdb.xcache = xcache
+				# for package.use.mask support inside dep_check
+				dep_settings.setcpv("/".join((catdir, y)))
+				dep_settings["ACCEPT_KEYWORDS"] = " ".join(groups)
+				# just in case, prevent config.reset() from nuking these.
+				dep_settings.backup_changes("ACCEPT_KEYWORDS")
+
+				for myprovide in myaux["PROVIDE"].split():
+					prov_cp = portage.dep_getkey(myprovide)
+					if prov_cp not in dep_settings.getvirtuals():
+						stats["virtual.unavailable"]+=1
+						fails["virtual.unavailable"].append(x+"/"+y+".ebuild: "+keyword+"("+prof[0]+") "+prov_cp)
+
+				if not baddepsyntax:
+					ismasked = os.path.join(catdir, y) not in \
+						portdb.xmatch("list-visible", x)
+					if ismasked:
+						if "--ignore-masked" in myoptions:
+							continue
+						#we are testing deps for a masked package; give it some lee-way
+						suffix="masked"
+						matchmode="match-all"
+					else:
+						suffix=""
+						matchmode="match-visible"
+	
+					if prof[1] == "dev":
+						suffix=suffix+"indev"
+
+					for mytype,mypos in [["DEPEND",len(missingvars)],["RDEPEND",len(missingvars)+1],["PDEPEND",len(missingvars)+2]]:
+						
+						mykey=mytype+".bad"+suffix
+						myvalue = myaux[mytype]
+						if not myvalue:
+							continue
+						try:
+							mydep = portage.dep_check(myvalue, portdb,
+								dep_settings, use="all", mode=matchmode,
+								trees=trees)
+						except KeyError, e:
+							stats[mykey]=stats[mykey]+1
+							fails[mykey].append(x+"/"+y+".ebuild: "+keyword+"("+prof[0]+") "+repr(e[0]))
+							continue
+	
+						if mydep[0]==1:
+							if mydep[1]!=[]:
+								#we have some unsolvable deps
+								#remove ! deps, which always show up as unsatisfiable
+								d=0
+								while d<len(mydep[1]):
+									if mydep[1][d][0]=="!":
+										del mydep[1][d]
+									else:
+										d += 1
+								#if we emptied out our list, continue:
+								if not mydep[1]:
+									continue
+								stats[mykey]=stats[mykey]+1
+								fails[mykey].append(x+"/"+y+".ebuild: "+keyword+"("+prof[0]+") "+repr(mydep[1]))
+						else:
+							stats[mykey]=stats[mykey]+1
+							fails[mykey].append(x+"/"+y+".ebuild: "+keyword+"("+prof[0]+") "+repr(mydep[1]))
+
+		# this check needs work, it won't catch (\ndie)
+		if not os.system("egrep '^[^#]*\([^)]*\<die\>' "+checkdir+"/"+y+".ebuild >/dev/null 2>&1"):
+			stats["ebuild.nesteddie"]=stats["ebuild.nesteddie"]+1
+			fails["ebuild.nesteddie"].append(x+"/"+y+".ebuild")
+		# uselist checks - global
+		myuse = []
+		default_use = []
+		for myflag in myaux["IUSE"].split():
+			if myflag.startswith("+"):
+				default_use.append(myflag)
+				myflag = myflag[1:]
+			myuse.append(myflag)
+		for mypos in range(len(myuse)-1,-1,-1):
+			if myuse[mypos] and (myuse[mypos] in uselist):
+				del myuse[mypos]
+		# uselist checks - local
+		mykey = portage.dep_getkey(catpkg)
+		if luselist.has_key(mykey):
+			for mypos in range(len(myuse)-1,-1,-1):
+				if myuse[mypos] and (myuse[mypos] in luselist[mykey]):
+					del myuse[mypos]
+		if default_use and myaux["EAPI"] == "0":
+			myuse += default_use
+		for mypos in range(len(myuse)):
+			stats["IUSE.invalid"]=stats["IUSE.invalid"]+1
+			fails["IUSE.invalid"].append(x+"/"+y+".ebuild: %s" % myuse[mypos])	
+
+		# license checks
+		if not badlicsyntax:
+			myuse = myaux["LICENSE"]
+			# Parse the LICENSE variable, remove USE conditions and
+			# flatten it.
+			myuse=portage_dep.use_reduce(portage_dep.paren_reduce(myuse), matchall=1)
+			myuse=portage.flatten(myuse)
+			# Check each entry to ensure that it exists in PORTDIR's
+			# license directory.
+			for mypos in range(0,len(myuse)):
+				# Need to check for "||" manually as no portage
+				# function will remove it without removing values.
+				if myuse[mypos] not in liclist and myuse[mypos] != "||":
+					stats["LICENSE.invalid"]=stats["LICENSE.invalid"]+1
+					fails["LICENSE.invalid"].append(x+"/"+y+".ebuild: %s" % myuse[mypos])
+
+		#keyword checks
+		myuse = myaux["KEYWORDS"].split()
+		for mykey in myuse:
+			myskey=mykey[:]
+			if myskey[0]=="-":
+				myskey=myskey[1:]
+			if myskey[0]=="~":
+				myskey=myskey[1:]
+			if mykey!="-*":
+				if myskey not in kwlist:
+					stats["KEYWORDS.invalid"] += 1
+					fails["KEYWORDS.invalid"].append(x+"/"+y+".ebuild: %s" % mykey)
+				elif not profiles.has_key(myskey):
+					stats["KEYWORDS.invalid"] += 1
+					fails["KEYWORDS.invalid"].append(x+"/"+y+".ebuild: %s (profile invalid)" % mykey)
+
+		#syntax checks
+		myear = time.gmtime(os.stat(checkdir+"/"+y+".ebuild")[ST_MTIME])[0]
+		gentoo_copyright = re.compile(r'^# Copyright ((1999|200\d)-)?' + str(myear) + r' Gentoo Foundation')
+		gentoo_license = re.compile(r'^# Distributed under the terms of the GNU General Public License v2$')
+		cvs_header = re.compile(r'^#\s*\$Header.*\$$')
+		ignore_line = re.compile(r'(^$)|(^(\t)*#)')
+		leading_spaces = re.compile(r'^[\S\t]')
+		trailing_whitespace = re.compile(r'.*([\S]$)')
+		readonly_assignment = re.compile(r'^\s*(export\s+)?(A|CATEGORY|P|PV|PN|PR|PVR|PF|D|WORKDIR|FILESDIR|FEATURES|USE)=')
+		line_continuation = re.compile(r'([^#]*\S)(\s+|\t)\\$')
+		linenum=0
+		previous_line = None
+		for line in input(checkdir+"/"+y+".ebuild"):
+			linenum += 1
+			# Gentoo copyright check
+			if linenum == 1:
+				match = gentoo_copyright.match(line)
+				if not match:
+					myerrormsg = "Copyright header Error. Possibly date related."
+					stats["ebuild.badheader"] +=1
+					fails["ebuild.badheader"].append(x+"/"+y+".ebuild: %s" % myerrormsg)
+			# Gentoo license check
+			elif linenum == 2:
+				match = gentoo_license.match(line)
+				if not match:
+					myerrormsg = "Gentoo License Error."
+					stats["ebuild.badheader"] +=1
+					fails["ebuild.badheader"].append(x+"/"+y+".ebuild: %s" % myerrormsg)
+			# CVS Header check
+			elif linenum == 3:
+				match = cvs_header.match(line)
+				if not match:
+					myerrormsg = "CVS Header Error."
+					stats["ebuild.badheader"] +=1
+					fails["ebuild.badheader"].append(x+"/"+y+".ebuild: %s" % myerrormsg)
+			else:
+				match = ignore_line.match(line)
+				if not match:
+					# Excluded Blank lines and full line comments. Good!
+					# Leading Spaces Check
+					match = leading_spaces.match(line)
+					if not match:
+						#Line has got leading spaces. Bad!
+						myerrormsg = "Leading Space Syntax Error. Line %d" % linenum
+						stats["ebuild.minorsyn"] +=1
+						fails["ebuild.minorsyn"].append(x+"/"+y+".ebuild: %s" % myerrormsg)
+					# Trailing whitespace check
+					match = trailing_whitespace.match(line)
+					if not match:
+						#Line has got trailing whitespace. Bad!
+						myerrormsg = "Trailing whitespace Syntax Error. Line %d" % linenum
+						stats["ebuild.minorsyn"] +=1
+						fails["ebuild.minorsyn"].append(x+"/"+y+".ebuild: %s" % myerrormsg)
+					# Readonly variable assignment check
+					match = readonly_assignment.match(line)
+					# The regex can give a false positive for continued lines,
+					# so we check the previous line to see if it was continued.
+					if match and (not previous_line or not line_continuation.match(previous_line)):
+						# invalid assignment, very bad!
+						myerrormsg = "Readonly variable assignment to %s on line %d" % (match.group(2), linenum)
+						stats["variable.readonly"] += 1
+						fails["variable.readonly"].append(x+"/"+y+".ebuild: %s" % myerrormsg)
+			previous_line = line
+		del previous_line
+
+	# Check for 'all unstable' or 'all masked' -- ACCEPT_KEYWORDS is stripped
+	# XXX -- Needs to be implemented in dep code. Can't determine ~arch nicely.
+	#if not portage.portdb.xmatch("bestmatch-visible",x):
+	#    stats["ebuild.nostable"]+=1
+	#    fails["ebuild.nostable"].append(x)
+	if allmasked and repolevel == 3:
+		stats["ebuild.allmasked"]+=1
+		fails["ebuild.allmasked"].append(x)
+
+#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)
+if quiet < 2:
+	print
+#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
+for x in qacats:
+	if not isCvs and x.find("notadded") != -1:
+		stats[x] = 0
+	if stats[x]:
+		dowarn=1
+		if x not in qawarnings:
+			dofail=1
+	else:
+		continue
+	print "  "+x.ljust(30),
+	if stats[x]==0:
+		print green(`stats[x]`)
+		continue
+	elif x in qawarnings:
+		print yellow(`stats[x]`)
+	else:
+		print red(`stats[x]`)
+	if mymode!="full":
+		if stats[x]<12:
+			for y in fails[x]:
+				print "   "+y
+		else:
+			dofull=1
+	else:
+		for y in fails[x]:
+			print "   "+y
+
+def grouplist(mylist,seperator="/"):
+	"""(list,seperator="/") -- Takes a list of elements; groups them into
+	same initial element categories. Returns a dict of {base:[sublist]}
+	From: ["blah/foo","spork/spatula","blah/weee/splat"]
+	To:   {"blah":["foo","weee/splat"], "spork":["spatula"]}"""
+	mygroups={}
+	for x in mylist:
+		xs=x.split(seperator)
+		if xs[0]==".":
+			xs=xs[1:]
+		if xs[0] not in mygroups.keys():
+			mygroups[xs[0]]=[seperator.join(xs[1:])]
+		else:
+			mygroups[xs[0]]+=[seperator.join(xs[1:])]
+	return mygroups
+
+if mymode!="commit":
+	if dofull:
+		print bold("Note: type \"repoman full\" for a complete listing.")
+		if quiet < 1:
+			print
+	if dowarn and not dofail:
+		if quiet < 2:
+			print green("RepoMan sez:"),"\"You're only giving me a partial QA payment?\n              I'll take it this time, but I'm not happy.\""
+		else:
+			print green("RepoMan sez:"),"\"OK for now, but I'll be back ...\""
+	elif not dofail:
+		print green("RepoMan sez:"),"\"If everyone were like you, I'd be out of business!\""
+	if quiet < 1:
+		print
+else:
+	if dofail:
+		print turquoise("Please fix these important QA issues first.")
+		print green("RepoMan sez:"),"\"Make your QA payment on time and you'll never see the likes of me.\"\n"
+		sys.exit(1)
+
+	if "--pretend" in myoptions:
+		print green("RepoMan sez:"), "\"So, you want to play it safe. Good call.\"\n"
+
+	if fails["digest.missing"]:
+		print green("Creating missing digests...")
+	for x in fails["digest.missing"]:
+		xs=x.split("/")
+		del xs[-2]
+		myeb="/".join(xs[:-1])+"/"+xs[-1][7:]
+		if "--pretend" in myoptions:
+			print "(ebuild "+portdir+"/"+myeb+".ebuild digest)"
+		else:
+			retval=os.system("ebuild "+portdir+"/"+myeb+".ebuild digest")
+			if retval:
+				print "!!! Exiting on ebuild digest (shell) error code:",retval
+				sys.exit(retval)
+
+	mycvstree=cvstree.getentries("./",recursive=1)
+	if isCvs and not mycvstree:
+		print "!!! It seems we don't have a cvs tree?"
+		sys.exit(3)
+
+	myunadded=cvstree.findunadded(mycvstree,recursive=1,basedir="./")
+	myautoadd=[]
+	if myunadded:
+		for x in range(len(myunadded)-1,-1,-1):
+			xs=myunadded[x].split("/")
+			if xs[-1]=="files":
+				print "!!! files dir is not added! Please correct this."
+				sys.exit(-1)
+			elif xs[-1]=="Manifest":
+				# It's a manifest... auto add
+				myautoadd+=[myunadded[x]]
+				del myunadded[x]
+			elif len(xs[-1])>=7:
+				if xs[-1][:7]=="digest-":
+					del xs[-2]
+					myeb="/".join(xs[:-1]+[xs[-1][7:]])+".ebuild"
+					if os.path.exists(myeb):
+						# Ebuild exists for digest... So autoadd it.
+						myautoadd+=[myunadded[x]]
+						del myunadded[x]
+		
+	if myautoadd:
+		print ">>> Auto-Adding missing digests..."
+		if "--pretend" in myoptions:
+			print "(/usr/bin/cvs add "+" ".join(myautoadd)+")"
+			retval=0
+		else:
+			retval=os.system("/usr/bin/cvs add "+" ".join(myautoadd))
+		if retval:
+			print "!!! Exiting on cvs (shell) error code:",retval
+			sys.exit(retval)
+
+	if myunadded:
+		print red("!!! The following files are in your cvs tree but are not added to the master")
+		print red("!!! tree. Please remove them from the cvs tree or add them to the master tree.")
+		for x in myunadded:
+			print "   ",x
+		print
+		print
+		sys.exit(1)
+
+	retval=["",""]
+	if isCvs:
+		print "Performing a "+green("cvs -n up")+" with a little magic grep to check for updates."
+		retval=getstatusoutput("/usr/bin/cvs -n up 2>&1 | egrep '^[^\?] .*' | egrep -v '^. .*/digest-[^/]+|^cvs server: .* -- ignored$'")
+		
+	mylines=retval[1].split("\n")
+	myupdates=[]
+	for x in mylines:
+		if not x:
+			continue
+		if x[0] not in "UPMAR": # Updates,Patches,Modified,Added,Removed
+			print red("!!! Please fix the following issues reported from cvs: ")+green("(U,P,M,A,R are ok)")
+			print red("!!! Note: This is a pretend/no-modify pass...")
+			print retval[1]
+			print
+			sys.exit(1)
+		elif x[0] in ["U","P"]:
+			myupdates+=[x[2:]]
+	
+	if myupdates:
+		print green("Fetching trivial updates...")
+		if "--pretend" in myoptions:
+			print "(/usr/bin/cvs up "+" ".join(myupdates)+")"
+			retval=0
+		else:
+			retval=os.system("/usr/bin/cvs up "+" ".join(myupdates))
+		if retval!=0:
+			print "!!! cvs exited with an error. Terminating."
+			sys.exit(retval)
+	
+	if isCvs:
+		mycvstree=cvstree.getentries("./",recursive=1)
+		mychanged=cvstree.findchanged(mycvstree,recursive=1,basedir="./")
+		mynew=cvstree.findnew(mycvstree,recursive=1,basedir="./")
+		myremoved=cvstree.findremoved(mycvstree,recursive=1,basedir="./")
+		if not (mychanged or mynew or myremoved):
+			print
+			print green("RepoMan sez:"), "\"Doing nothing is not always good for QA.\"\n"
+			print
+			print "(Didn't find any changed files...)"
+			print
+			sys.exit(0)
+
+	# Manifests need to be regenerated after all other commits, so don't commit
+	# them now even if they have changed.
+	mymanifests = [f for f in mychanged if "Manifest" == os.path.basename(f)]
+	mychanged = [f for f in mychanged if "Manifest" != os.path.basename(f)]
+	myupdates=mychanged+mynew
+	myheaders=[]
+	mydirty=[]
+	headerstring="'\$(Header|Id)"
+	headerstring+=".*\$'"
+	for myfile in myupdates:
+		myout=getstatusoutput("egrep -q "+headerstring+" "+myfile)
+		if myout[0]==0:
+			myheaders.append(myfile)
+
+	print "*",green(str(len(myupdates))),"files being committed...",green(str(len(myheaders))),"have headers that will change."
+	print "*","Files with headers will cause the manifests to be made and recommited."
+	if quiet == 0:
+		print "myupdates:",myupdates
+		print "myheaders:",myheaders
+		print
+
+	if commitmessagefile:
+		try:
+			f = open(commitmessagefile)
+			commitmessage = f.read()
+			f.close()
+			del f
+		except (IOError, OSError), e:
+			if e.errno == errno.ENOENT:
+				portage.writemsg("!!! File Not Found: --commitmsgfile='%s'\n" % commitmessagefile)
+			else:
+				raise
+		# We've read the content so the file is no longer needed.
+		commitmessagefile = None
+	if not commitmessage:
+		print "Please enter a CVS commit message at the prompt:"
+		while not commitmessage:
+			try:
+				commitmessage=raw_input(green("> "))
+			except KeyboardInterrupt: 
+				exithandler()
+	try:
+		commitmessage+="\n(Portage version: "+str(portage.VERSION)+")"
+	except AttributeError:
+		print "Failed to insert portage version in message!"
+		commitmessage+="\n(Portage version: Unknown)"
+
+	if not manifest1_compat:
+		myfiles = myupdates + myremoved + mymanifests
+		filesdirs = set()
+		if repolevel == 3:
+			filesdirs.add(os.path.join(".", "files"))
+		elif repolevel in (1, 2):
+			for x in myfiles:
+				xs = x.split(os.path.sep)
+				if len(xs) < 4-repolevel:
+					continue
+				xs = xs[0:4-repolevel]
+				xs.append("files")
+				filesdirs.add(os.path.join(*xs))
+		else:
+			raise AssertionError("repolevel=%s" % str(repolevel))
+		digest_files = []
+		for x in filesdirs:
+			dir_path = os.path.join(startdir, x)
+			if not os.path.isdir(dir_path):
+				continue
+			for y in os.listdir(dir_path):
+				if y.startswith("digest-"):
+					digest_files.append(os.path.join(x, y))
+		if digest_files:
+			digest_files.sort()
+			if "--pretend" in myoptions:
+				print "(rm %s)" % " ".join(digest_files)
+				print "(/usr/bin/cvs remove %s)" % " ".join(digest_files)
+			else:
+				for x in digest_files:
+					os.unlink(os.path.join(startdir, x))
+				retval = spawn(["/usr/bin/cvs", "remove"] + digest_files,
+					env=os.environ)
+				if retval != os.EX_OK:
+					print "!!! Exiting on cvs (shell) error code:",retval
+					sys.exit(retval)
+			myremoved.extend(digest_files)
+			myremoved = list(set(myremoved))
+			myremoved.sort()
+
+	if myupdates or myremoved:
+		myfiles = myupdates + myremoved
+		fd, commitmessagefile = tempfile.mkstemp(".repoman.msg")
+		mymsg = os.fdopen(fd, "w")
+		mymsg.write(commitmessage)
+		mymsg.close()
+
+		print
+		print green("Using commit message:")
+		print green("------------------------------------------------------------------------------")
+		print commitmessage
+		print green("------------------------------------------------------------------------------")
+		print
+
+		retval = None
+		if "--pretend" in myoptions:
+			print "(/usr/bin/cvs -q commit -F %s %s)" % \
+				(commitmessagefile, " ".join(myfiles))
+		else:
+			retval = spawn(["/usr/bin/cvs", "-q", "commit",
+				"-F", commitmessagefile] + myfiles,
+				env=os.environ)
+		try:
+			os.unlink(commitmessagefile)
+		except OSError:
+			pass
+		if retval:
+			print "!!! Exiting on cvs (shell) error code:",retval
+			sys.exit(retval)
+
+	# Setup the GPG commands
+	def gpgsign(filename):
+		if "PORTAGE_GPG_KEY" not in repoman_settings:
+			raise portage_exception.MissingParameter("PORTAGE_GPG_KEY is unset!")
+		if "PORTAGE_GPG_DIR" not in repoman_settings:
+			if os.environ.has_key("HOME"):
+				repoman_settings["PORTAGE_GPG_DIR"] = os.path.join(os.environ["HOME"], ".gnupg")
+				if quiet < 1:
+					print "Automatically setting PORTAGE_GPG_DIR to",repoman_settings["PORTAGE_GPG_DIR"]
+			else:
+				raise portage_exception.MissingParameter("PORTAGE_GPG_DIR is unset!")
+		gpg_dir = repoman_settings["PORTAGE_GPG_DIR"]
+		if gpg_dir.startswith("~") and "HOME" in os.environ:
+			repoman_settings["PORTAGE_GPG_DIR"] = os.path.join(
+				os.environ["HOME"], gpg_dir[1:].lstrip(os.path.sep))
+		if not os.access(repoman_settings["PORTAGE_GPG_DIR"], os.X_OK):
+			raise portage_exception.InvalidLocation(
+				"Unable to access directory: PORTAGE_GPG_DIR='%s'" % \
+				repoman_settings["PORTAGE_GPG_DIR"])
+		gpgcmd = "gpg --sign --clearsign --yes "
+		gpgcmd+= "--default-key "+repoman_settings["PORTAGE_GPG_KEY"]
+		if repoman_settings.has_key("PORTAGE_GPG_DIR"):
+			gpgcmd += " --homedir "+repoman_settings["PORTAGE_GPG_DIR"]
+		if "--pretend" in myoptions:
+			print "("+gpgcmd+" "+filename+")"
+		else:
+			rValue = os.system(gpgcmd+" "+filename)
+			if rValue == os.EX_OK:
+				os.rename(filename+".asc", filename)
+			else:
+				raise portage_exception.PortageException("!!! gpg exited with '" + str(rValue) + "' status")
+
+	manifest_commit_required = True
+	if myheaders or myupdates or myremoved or mynew:
+		myfiles=myheaders+myupdates+myremoved+mynew
+		for x in range(len(myfiles)-1, -1, -1):
+			if myfiles[x].count("/") < 4-repolevel:
+				del myfiles[x]
+		mydone=[]
+		if repolevel==3:   # In a package dir
+			repoman_settings["O"] = startdir
+			portage.digestgen([], repoman_settings, manifestonly=1,
+				myportdb=portdb)
+		elif repolevel==2: # In a category dir
+			for x in myfiles:
+				xs=x.split("/")
+				if len(xs) < 4-repolevel:
+					continue
+				if xs[0]==".":
+					xs=xs[1:]
+				if xs[0] in mydone:
+					continue
+				mydone.append(xs[0])
+				repoman_settings["O"] = os.path.join(startdir, xs[0])
+				if not os.path.isdir(repoman_settings["O"]):
+					continue
+				portage.digestgen([], repoman_settings, manifestonly=1,
+					myportdb=portdb)
+		elif repolevel==1: # repo-cvsroot
+			print green("RepoMan sez:"), "\"You're rather crazy... doing the entire repository.\"\n"
+			for x in myfiles:
+				xs=x.split("/")
+				if len(xs) < 4-repolevel:
+					continue
+				if xs[0]==".":
+					xs=xs[1:]
+				if "/".join(xs[:2]) in mydone:
+					continue
+				mydone.append("/".join(xs[:2]))
+				repoman_settings["O"] = os.path.join(startdir, xs[0], xs[1])
+				if not os.path.isdir(repoman_settings["O"]):
+					continue
+				portage.digestgen([], repoman_settings, manifestonly=1,
+					myportdb=portdb)
+		else:
+			print red("I'm confused... I don't know where I am!")
+			sys.exit(1)
+
+		# Force an unsigned commit when more than one Manifest needs to be signed.
+		if repolevel < 3 and "sign" in repoman_settings.features:
+			if "--pretend" in myoptions:
+				print "(/usr/bin/cvs -q commit -F commitmessagefile)"
+			else:
+				fd, commitmessagefile = tempfile.mkstemp(".repoman.msg")
+				mymsg = os.fdopen(fd, "w")
+				mymsg.write(commitmessage)
+				mymsg.write("\n (Unsigned Manifest commit)")
+				mymsg.close()
+				retval=os.system("/usr/bin/cvs -q commit -F "+commitmessagefile)
+				try:
+					os.unlink(commitmessagefile)
+				except OSError:
+					pass
+				if retval:
+					print "!!! Exiting on cvs (shell) error code:",retval
+					sys.exit(retval)
+			manifest_commit_required = False
+
+	signed = False
+	if "sign" in repoman_settings.features:
+		signed = True
+		myfiles = myupdates + myremoved + mymanifests
+		try:
+			if repolevel==3:   # In a package dir
+				repoman_settings["O"] = "."
+				gpgsign(os.path.join(repoman_settings["O"], "Manifest"))
+			elif repolevel==2: # In a category dir
+				mydone=[]
+				for x in myfiles:
+					xs=x.split("/")
+					if len(xs) < 4-repolevel:
+						continue
+					if xs[0]==".":
+						xs=xs[1:]
+					if xs[0] in mydone:
+						continue
+					mydone.append(xs[0])
+					repoman_settings["O"] = os.path.join(".", xs[0])
+					if not os.path.isdir(repoman_settings["O"]):
+						continue
+					gpgsign(os.path.join(repoman_settings["O"], "Manifest"))
+			elif repolevel==1: # repo-cvsroot
+				print green("RepoMan sez:"), "\"You're rather crazy... doing the entire repository.\"\n"
+				mydone=[]
+				for x in myfiles:
+					xs=x.split("/")
+					if len(xs) < 4-repolevel:
+						continue
+					if xs[0]==".":
+						xs=xs[1:]
+					if "/".join(xs[:2]) in mydone:
+						continue
+					mydone.append("/".join(xs[:2]))
+					repoman_settings["O"] = os.path.join(".", xs[0], xs[1])
+					if not os.path.isdir(repoman_settings["O"]):
+						continue
+					gpgsign(os.path.join(repoman_settings["O"], "Manifest"))
+		except portage_exception.PortageException, e:
+			portage.writemsg("!!! %s\n" % str(e))
+			portage.writemsg("!!! Disabled FEATURES='sign'\n")
+			signed = False
+
+	if manifest_commit_required or signed:
+		if "--pretend" in myoptions:
+			print "(/usr/bin/cvs -q commit -F commitmessagefile)"
+		else:
+			fd, commitmessagefile = tempfile.mkstemp(".repoman.msg")
+			mymsg = os.fdopen(fd, "w")
+			mymsg.write(commitmessage)
+			if signed:
+				mymsg.write("\n (Signed Manifest commit)")
+			else:
+				mymsg.write("\n (Unsigned Manifest commit)")
+			mymsg.close()
+			retval=os.system("/usr/bin/cvs -q commit -F "+commitmessagefile)
+			try:
+				os.unlink(commitmessagefile)
+			except OSError:
+				pass
+			if retval:
+				print "!!! Exiting on cvs (shell) error code:",retval
+				sys.exit(retval)
+
+	print
+	if isCvs:
+		print "CVS commit complete."
+	else:
+		print "repoman was too scared by not seeing any familiar cvs file that he forgot to commit anything"
+	print green("RepoMan sez:"), "\"If everyone were like you, I'd be out of business!\"\n"
+sys.exit(0)
+
Index: /vendor/portage/current/bin/sed
===================================================================
--- /vendor/portage/current/bin/sed	(revision 3419)
+++ /vendor/portage/current/bin/sed	(revision 3419)
@@ -0,0 +1,26 @@
+#!/bin/bash
+# Copyright 2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+ 
+scriptpath="${BASH_SOURCE[0]}"
+
+if [[ -n ${ESED} ]]; then
+	exec ${ESED} "$@"
+elif type -P gsed > /dev/null ; then
+	exec gsed "$@"
+else
+	old_IFS="${IFS}"
+	IFS=":"
+ 
+	for path in $PATH; do
+		[[ ${path}/sed == $scriptpath ]] && continue
+		if [[ -x $path/sed ]]; then
+			exec $path/sed "$@"	
+			exit 0
+		fi
+	done
+	
+	IFS="${old_IFS}"
+fi
+ 
+exit 1
Index: /vendor/portage/current/bin/xpak
===================================================================
--- /vendor/portage/current/bin/xpak	(revision 3419)
+++ /vendor/portage/current/bin/xpak	(revision 3419)
@@ -0,0 +1,18 @@
+#!/usr/bin/python -O
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: xpak 4884 2006-10-31 04:23:06Z zmedico $
+
+import sys, os
+if len(sys.argv)!=3:
+	print "xpak: expecting three arguments."
+	sys.exit(1)
+
+try:
+	import xpak
+except ImportError:
+	from os import path as osp
+	sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
+	import xpak
+
+xpak.xpak(sys.argv[1],sys.argv[2])
Index: /vendor/portage/current/cnf/dispatch-conf.conf
===================================================================
--- /vendor/portage/current/cnf/dispatch-conf.conf	(revision 3419)
+++ /vendor/portage/current/cnf/dispatch-conf.conf	(revision 3419)
@@ -0,0 +1,39 @@
+#
+# dispatch-conf.conf
+#
+
+# Directory to archive replaced configs
+archive-dir=/etc/config-archive
+
+# Use rcs for storing files in the archive directory?
+# (yes or no)
+use-rcs=no
+
+# Diff for display
+# %s old file
+# %s new file
+diff="diff -Nu %s %s | less --no-init --QUIT-AT-EOF"
+
+# Diff for interactive merges.
+# %s output file
+# %s old file
+# %s new file
+merge="sdiff --suppress-common-lines --output=%s %s %s"
+
+# Automerge files comprising only CVS interpolations (e.g. Header or Id)
+# (yes or no)
+replace-cvs=yes
+
+# Automerge files comprising only whitespace and/or comments
+# (yes or no)
+replace-wscomments=no
+
+# Automerge files that the user hasn't modified
+# (yes or no)
+replace-unmodified=no
+
+# Per-session log file of changes made to configuration files
+#log-file=/var/log/dispatch-conf.log
+
+# List of frozen files for which dispatch-conf will automatically zap updates
+#frozen-files=""
Index: /vendor/portage/current/cnf/etc-update.conf
===================================================================
--- /vendor/portage/current/cnf/etc-update.conf	(revision 3419)
+++ /vendor/portage/current/cnf/etc-update.conf	(revision 3419)
@@ -0,0 +1,75 @@
+# edit the lines below to your liking
+# $Id: etc-update.conf 3483 2006-06-10 21:40:40Z genone $
+
+# mode - 0 for text, 1 for menu (support incomplete)
+# note that you need dev-util/dialog installed
+mode="0"
+
+# Whether trivial/comment changes should be automerged
+eu_automerge="yes"
+
+# arguments used whenever rm is called
+rm_opts="-i"
+
+# arguments used whenever mv is called
+mv_opts="-i"
+
+# arguments used whenever cp is called
+cp_opts="-i"
+
+# pager for use with diff commands (see NOTE_2)
+pager="less"
+#pager=""
+
+# For emacs-users
+# diff_command="eval emacs -nw --eval=\(ediff\ \"%file1\"\ \"%file2\"\)"
+#using_editor=1
+
+# vim-users: you CAN use vimdiff for diff_command. (see NOTE_1)
+#diff_command="vim -d %file1 %file2"
+#using_editor=1
+
+diff_command="diff -uN %file1 %file2"
+using_editor=0
+
+
+# vim-users: don't use vimdiff for merging (see NOTE_1)
+merge_command="sdiff -s -o %merged %orig %new"
+
+# EXPLANATION
+#
+# pager:
+#
+# Examples of pager usage:
+#	pager=""		# don't use a pager
+#	pager="less -E"	# less
+#	pager="more"	# more
+#
+#
+# diff_command:
+#
+# Arguments:
+#	%file1	[REQUIRED]
+#	%file2	[REQUIRED]
+#
+# Examples of diff_command:
+#	diff_command="diff -uN %file1 %file2"	# diff
+#	diff_command="vim -d %file1 %file2"		# vimdiff
+#
+#
+# merge_command:
+#
+# Arguments:
+#	%orig	[REQUIRED]
+#   %new    [REQUIRED]
+#	%merged	[REQUIRED]
+#
+# Examples of merge_command:
+#	merge_command="sdiff -s -o %merged %old %new"	# sdiff
+#
+
+# NOTE_1: Editors such as vim/vimdiff are not usable for the merge_command
+# because it is not known what filenames the produced files have (the user can
+# choose while using those programs)
+
+# NOTE_2: Make sure pager is set to "" when using an editor as diff_command!
Index: /vendor/portage/current/cnf/make.conf
===================================================================
--- /vendor/portage/current/cnf/make.conf	(revision 3419)
+++ /vendor/portage/current/cnf/make.conf	(revision 3419)
@@ -0,0 +1,386 @@
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: make.conf 5544 2007-01-11 07:19:34Z genone $
+# Contains local system settings for Portage system
+
+# Please review 'man make.conf' for more information.
+
+# Build-time functionality
+# ========================
+#
+# The USE variable is used to enable optional build-time functionality. For
+# example, quite a few packages have optional X, gtk or GNOME functionality
+# that can only be enabled or disabled at compile-time. Gentoo Linux has a
+# very extensive set of USE variables described in our USE variable HOWTO at
+# http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=2&chap=1
+#
+# The available list of use flags with descriptions is in your portage tree.
+# Use 'less' to view them:  --> less /usr/portage/profiles/use.desc <--
+#
+# 'ufed' is an ncurses/dialog interface available in portage to make handling
+# useflags for you. 'emerge app-portage/ufed'
+#
+# Example:
+#USE="X gtk gnome -alsa"
+
+# Host and optimization settings 
+# ==============================
+#
+# For optimal performance, enable a CFLAGS setting appropriate for your CPU.
+#
+# Please note that if you experience strange issues with a package, it may be
+# due to gcc's optimizations interacting in a strange way. Please test the
+# package (and in some cases the libraries it uses) at default optimizations
+# before reporting errors to developers.
+#
+# Please refer to the GCC manual for a list of possible values.
+#
+#CFLAGS="-O2 -pipe"
+#
+# If you set a CFLAGS above, then this line will set your default C++ flags to
+# the same settings.
+#CXXFLAGS="${CFLAGS}"
+
+# Advanced Masking
+# ================
+#
+# Gentoo is using a new masking system to allow for easier stability testing
+# on packages. KEYWORDS are used in ebuilds to mask and unmask packages based
+# on the platform they are set for. A special form has been added that
+# indicates packages and revisions that are expected to work, but have not yet
+# been approved for the stable set. '~arch' is a superset of 'arch' which
+# includes the unstable, in testing, packages. Users of the 'x86' architecture
+# would add '~x86' to ACCEPT_KEYWORDS to enable unstable/testing packages.
+# '~ppc', '~sparc' are the unstable KEYWORDS for their respective platforms.
+#
+# Please note that this is not for development, alpha, beta, nor cvs release
+# packages. "Broken" packages will not be added to testing and should not be
+# requested to be added. Alternative routes are available to developers
+# for experimental packages, and it is at their discretion to use them.
+#
+# DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+# IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+#
+#ACCEPT_KEYWORDS="~arch"
+
+# Portage Directories
+# ===================
+#
+# Each of these settings controls an aspect of portage's storage and file
+# system usage. If you change any of these, be sure it is available when
+# you try to use portage. *** DO NOT INCLUDE A TRAILING "/" ***
+#
+# PORTAGE_TMPDIR is the location portage will use for compilations and
+#     temporary storage of data. This can get VERY large depending upon
+#     the application being installed.
+#PORTAGE_TMPDIR=/var/tmp
+#
+# PORTDIR is the location of the portage tree. This is the repository
+#     for all profile information as well as all ebuilds. If you change
+#     this, you must update your /etc/make.profile symlink accordingly.
+#PORTDIR=/usr/portage
+#
+# DISTDIR is where all of the source code tarballs will be placed for
+#     emerges. The source code is maintained here unless you delete
+#     it. The entire repository of tarballs for Gentoo is 9G. This is
+#     considerably more than any user will ever download. 2-3G is
+#     a large DISTDIR.
+#DISTDIR=${PORTDIR}/distfiles
+#
+# PKGDIR is the location of binary packages that you can have created
+#     with '--buildpkg' or '-b' while emerging a package. This can get
+#     up to several hundred megs, or even a few gigs.
+#PKGDIR=${PORTDIR}/packages
+#
+# PORT_LOGDIR is the location where portage will store all the logs it
+#     creates from each individual merge. They are stored as NNNN-$PF.log
+#     in the directory specified. This is disabled until you enable it by
+#     providing a directory. Permissions will be modified as needed IF the
+#     directory exists, otherwise logging will be disabled. NNNN is the
+#     increment at the time the log is created. Logs are thus sequential.
+#PORT_LOGDIR=/var/log/portage
+#
+# PORTDIR_OVERLAY is a directory where local ebuilds may be stored without
+#     concern that they will be deleted by rsync updates. Default is not
+#     defined.
+#PORTDIR_OVERLAY=/usr/local/portage
+
+# Fetching files 
+# ==============
+#
+# If you need to set a proxy for wget or lukemftp, add the appropriate "export
+# ftp_proxy=<proxy>" and "export http_proxy=<proxy>" lines to /etc/profile if
+# all users on your system should use them.
+#
+# Portage uses wget by default. Here are some settings for some alternate
+# downloaders -- note that you need to merge these programs first before they
+# will be available.
+#
+# Default fetch command (5 tries, passive ftp for firewall compatibility)
+#FETCHCOMMAND="/usr/bin/wget -t 5 -T 60 --passive-ftp \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 -T 60 --passive-ftp \${URI} -P \${DISTDIR}"
+#
+# Using wget, ratelimiting downloads
+#FETCHCOMMAND="/usr/bin/wget -t 5 -T 60 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#RESUMECOMMAND="/usr/bin/wget -c -t 5 -T 60 --passive-ftp --limit-rate=200k \${URI} -P \${DISTDIR}"
+#
+# Lukemftp (BSD ftp):
+#FETCHCOMMAND="/usr/bin/lukemftp -s -a -o \${DISTDIR}/\${FILE} \${URI}"
+#RESUMECOMMAND="/usr/bin/lukemftp -s -a -R -o \${DISTDIR}/\${FILE} \${URI}"
+#
+# Portage uses GENTOO_MIRRORS to specify mirrors to use for source retrieval.
+# The list is a space separated list which is read left to right. If you use
+# another mirror we highly recommend leaving the default mirror at the end of
+# the list so that portage will fall back to it if the files cannot be found
+# on your specified mirror. We _HIGHLY_ recommend that you change this setting
+# to a nearby mirror by merging and using the 'mirrorselect' tool.
+#GENTOO_MIRRORS="<your_mirror_here> http://distfiles.gentoo.org http://www.ibiblio.org/pub/Linux/distributions/gentoo"
+#
+# Portage uses PORTAGE_BINHOST to specify mirrors for prebuilt-binary packages.
+# The list is a single entry specifying the full address of the directory
+# serving the tbz2's for your system. Running emerge with either '--getbinpkg'
+# or '--getbinpkgonly' will cause portage to retrieve the metadata from all
+# packages in the directory specified, and use that data to determine what will
+# be downloaded and merged. '-g' or '-gK' are the recommend parameters. Please
+# consult the man pages and 'emerge --help' for more information. For FTP, the
+# default connection is passive -- If you require an active connection, affix
+# an asterisk (*) to the end of the host:port string before the path.
+#PORTAGE_BINHOST="http://grp.mirror.site/gentoo/grp/1.4/i686/athlon-xp/"
+# This ftp connection is passive ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site/pub/grp/i686/athlon-xp/"
+# This ftp connection is active ftp.
+#PORTAGE_BINHOST="ftp://login:pass@grp.mirror.site:21*/pub/grp/i686/athlon-xp/"
+
+# Synchronizing Portage
+# =====================
+#
+# Each of these settings affects how Gentoo synchronizes your Portage tree.
+# Synchronization is handled by rsync and these settings allow some control
+# over how it is done.
+#
+# SYNC is the server used by rsync to retrieve a localized rsync mirror
+#     rotation. This allows you to select servers that are geographically
+#     close to you, yet still distribute the load over a number of servers.
+#     Please do not single out specific rsync mirrors. Doing so places undue
+#     stress on particular mirrors.  Instead you may use one of the following
+#     continent specific rotations:
+#
+#   Default:       "rsync://rsync.gentoo.org/gentoo-portage"
+#   North America: "rsync://rsync.namerica.gentoo.org/gentoo-portage"
+#   South America: "rsync://rsync.samerica.gentoo.org/gentoo-portage"
+#   Europe:        "rsync://rsync.europe.gentoo.org/gentoo-portage"
+#   Asia:          "rsync://rsync.asia.gentoo.org/gentoo-portage"
+#   Australia:     "rsync://rsync.au.gentoo.org/gentoo-portage"
+#
+#     If you have multiple Gentoo boxes, it is probably a good idea to have only
+#     one of them sync from the rotations above. The other boxes can then rsync
+#     from the local rsync server, reducing the load on the mirrors.
+#     Instructions for setting up a local rsync server are available here:
+#     http://www.gentoo.org/doc/en/rsync.xml
+#
+#SYNC="rsync://rsync.gentoo.org/gentoo-portage"
+#
+# PORTAGE_RSYNC_RETRIES sets the number of times portage will attempt to retrieve
+#     a current portage tree before it exits with an error. This allows
+#     for a more successful retrieval without user intervention most times.
+#PORTAGE_RSYNC_RETRIES="3"
+#
+# PORTAGE_RSYNC_EXTRA_OPTS can be used to feed additional options to the rsync
+#     command used by `emerge --sync`. This will not change the default options
+#     which are set by PORTAGE_RSYNC_OPTS (don't change those unless you know 
+#     exactly what you're doing).
+#PORTAGE_RSYNC_EXTRA_OPTS=""
+#
+# Advanced Features
+# =================
+#
+# EMERGE_DEFAULT_OPTS allows emerge to act as if certain options are
+#     specified on every run. Useful options include --ask, --verbose,
+#     --usepkg and many others. Options that are not useful, such as --help,
+#     are not filtered.
+#EMERGE_DEFAULT_OPTS=""
+#
+# INSTALL_MASK allows certain files to not be installed into your file system.
+#     This is useful when you wish to filter out a certain set of files from
+#     ever being installed, such as INSTALL.gz or TODO.gz
+#INSTALL_MASK=""
+#
+# MAKEOPTS provides extra options that may be passed to 'make' when a
+#     program is compiled. Presently the only use is for specifying
+#     the number of parallel makes (-j) to perform. The suggested number
+#     for parallel makes is CPUs+1.
+#MAKEOPTS="-j2"
+#
+# PORTAGE_NICENESS provides a default increment to emerge's niceness level.
+#     Note: This is an increment. Running emerge in a niced environment will
+#     reduce it further. Default is unset.
+#PORTAGE_NICENESS=3
+#
+# AUTOCLEAN enables portage to automatically clean out older or overlapping
+#     packages from the system after every successful merge. This is the
+#     same as running 'emerge -c' after every merge. Set with: "yes" or "no".
+#     This does not affect the unpacked source. See 'noclean' below.
+#
+#     Warning: AUTOCLEAN="no" can cause serious problems due to overlapping
+#              packages.  Do not use it unless absolutely necessary!
+#AUTOCLEAN="yes"
+#
+# PORTAGE_TMPFS is a location where portage may create temporary files.
+#     If specified, portage will use this directory whenever possible
+#     for all rapid operations such as lockfiles and transient data.
+#     It is _highly_ recommended that this be a tmpfs or ramdisk. Do not
+#     set this to anything that does not give a significant performance
+#     enhancement and proper FS compliance for locks and read/write.
+#     /dev/shm is a glibc mandated tmpfs, and should be a reasonable
+#     setting for all linux kernel+glibc based systems.
+#PORTAGE_TMPFS="/dev/shm"
+#
+# FEATURES are settings that affect the functionality of portage. Most of
+#     these settings are for developer use, but some are available to non-
+#     developers as well. 
+#
+#  'assume-digests'
+#                when committing work to cvs with repoman(1), assume that all
+#                existing SRC_URI digests are correct.  This feature also
+#                affects digest generation via ebuild(1) and emerge(1) (emerge
+#                generates digests only when the 'digest' feature is enabled).
+#  'buildpkg'    causes binary packages to be created of all packages that 
+#                are being merged.
+#  'ccache'      enable support for the dev-util/ccache package, which can
+#                noticably decrease the time needed to remerge previously built
+#                packages.
+#  'confcache'   enable confcache support; speeds up autotool based configure
+#                calls
+#  'collision-protect'
+#                prevents packages from overwriting files that are owned by
+#                another package or by no package at all.
+#  'cvs'         causes portage to enable all cvs features (commits, adds),
+#                and to apply all USE flags in SRC_URI for digests -- for
+#                developers only.
+#  'digest'      autogenerate digests for packages when running the emerge(1)
+#                command.  If the 'assume-digests' feature is also enabled then
+#                existing SRC_URI digests will be reused whenever they are
+#                available.
+#  'distcc'      enables distcc support via CC.
+#  'distlocks'   enables distfiles locking using fcntl or hardlinks. This
+#                is enabled by default. Tools exist to help clean the locks
+#                after crashes: /usr/lib/portage/bin/clean_locks.
+#  'fixpackages' allows portage to fix binary packages that are stored in
+#                PKGDIR. This can consume a lot of time. 'fixpackages' is
+#                also a script that can be run at any given time to force
+#                the same actions.
+#  'gpg'         enables basic verification of Manifest files using gpg.
+#                This features is UNDER DEVELOPMENT and reacts to features
+#                of strict and severe. Heavy use of gpg sigs is coming.
+#  'keeptemp'    prevents the clean phase from deleting the temp files ($T) 
+#                from a merge.
+#  'keepwork'    prevents the clean phase from deleting the WORKDIR.
+#  'test'        causes ebuilds to perform testing phases if they are capable
+#                of it. Some packages support this automatically via makefiles.
+#  'metadata-transfer'
+#                automatically perform a metadata transfer when `emerge --sync`
+#                is run.
+#  'noauto'      causes ebuild to perform only the action requested and 
+#                not any other required actions like clean or unpack -- for
+#                debugging purposes only.
+#  'noclean'     prevents portage from removing the source and temporary files 
+#                after a merge -- for debugging purposes only. 
+#  'nostrip'     prevents the stripping of binaries.
+#  'notitles'    disables xterm titlebar updates (which contain status info). 
+#  'parallel-fetch'
+#                do fetching in parallel to compilation
+#  'sandbox'     enables sandboxing when running emerge and ebuild.
+#  'strict'      causes portage to react strongly to conditions that are
+#                potentially dangerous, like missing/incorrect Manifest files.
+#  'stricter'    causes portage to react strongly to conditions that may
+#                conflict with system security provisions (for example
+#                textrels, executable stacks).
+#  'userfetch'   when portage is run as root, drop privileges to
+#                portage:portage during the fetching of package sources.
+#  'userpriv'    allows portage to drop root privileges while it is compiling,
+#                as a security measure.  As a side effect this can remove 
+#                sandbox access violations for users. 
+#  'usersandbox' enables sandboxing while portage is running under userpriv.
+#FEATURES="sandbox buildpkg ccache distcc userpriv usersandbox notitles noclean noauto cvs keeptemp keepwork"
+#FEATURES="sandbox ccache distcc distlocks"
+
+# CCACHE_SIZE and CCACHE_DIR are used to control the behavior of ccache, and
+#     and are only used if "ccache" is in FEATURES.
+#
+# CCACHE_SIZE sets the space limitations for ccache. The default size is
+#     "2G", or 2 gigabytes.  Units are specified with 'G', 'M', or 'K'.
+#
+#CCACHE_SIZE="512M"
+#
+# CCACHE_DIR sets the ccache path.  If not specified, portage will default
+#     to "${PORTAGE_TMPDIR}/ccache".
+#
+#     Note that to display ccache statistics outside of portage, you must
+#     remember to give the correct path to the cache.
+#
+#        $ CCACHE_DIR=/var/tmp/ccache ccache -s 
+#
+#CCACHE_DIR="${PORTAGE_TMPDIR}/ccache"
+
+# DISTCC_DIR sets the temporary space used by distcc.
+#DISTCC_DIR="${PORTAGE_TMPDIR}/.distcc"
+
+# logging related variables:
+# PORTAGE_ELOG_CLASSES: selects messages to be logged, possible values are:
+#                          info, warn, error, log, qa
+#                       Warning: commenting this will disable elog
+PORTAGE_ELOG_CLASSES="warn error log"
+
+# PORTAGE_ELOG_SYSTEM: selects the module(s) to process the log messages. Modules
+#                      included in portage are (empty means logging is disabled):
+#                          save (saves one log per package in $PORT_LOGDIR/elog, 
+#                                /var/log/portage/elog if $PORT_LOGDIR is unset)
+#                          custom (passes all messages to $PORTAGE_ELOG_COMMAND)
+#                          syslog (sends all messages to syslog)
+#                          mail (send all messages to the mailserver defined 
+#                                in $PORTAGE_ELOG_MAILURI)
+#                          save_summary (like "save" but merges all messages
+#                                        in $PORT_LOGDIR/elog/summary.log,
+#                                        /var/log/portage/elog/summary.log if
+#                                        $PORT_LOGDIR is unset)
+#                          mail_summary (like "mail" but sends all messages in
+#                                        a single mail when emerge exits)
+#                      To use elog you should enable at least one module
+#PORTAGE_ELOG_SYSTEM="save mail"
+
+# PORTAGE_ELOG_COMMAND: only used with the "custom" logging module. Specifies a command
+#                      to process log messages. Two variables are expanded:
+#                          ${PACKAGE} - expands to the cpv entry of the processed 
+#                                       package (see $PVR in ebuild(5))
+#                          ${LOGFILE} - absolute path to the logfile
+#						Both variables have to be quoted with single quotes
+#PORTAGE_ELOG_COMMAND="/path/to/logprocessor -p '\${PACKAGE}' -f '\${LOGFILE}'"
+
+# PORTAGE_ELOG_MAILURI: this variable holds all important settings for the mail
+#                       module. In most cases listing the recipient address and
+#                       the receiving mailserver should be sufficient, but you can
+#                       also use advanced settings like authentication or TLS. The
+#                       full syntax is:
+#                           address [[user:passwd@]mailserver[:port]]
+#                       where
+#                           address:    recipient address
+#                           user:       username for smtp auth (defaults to none)
+#                           passwd:     password for smtp auth (defaults to none)
+#                           mailserver: smtp server that should be used to deliver the mail (defaults to localhost)
+#                                       alternatively this can also be a the path to a sendmail binary if you don't want to use smtp
+#                           port:       port to use on the given smtp server (defaults to 25, values > 100000 indicate that starttls should be used on (port-100000))
+#                       Examples:
+#PORTAGE_ELOG_MAILURI="root@localhost localhost" (this is also the default setting)
+#PORTAGE_ELOG_MAILURI="user@some.domain mail.some.domain" (sends mails to user@some.domain using the mailserver mail.some.domain)
+#PORTAGE_ELOG_MAILURI="user@some.domain user:secret@mail.some.domain:100465" (this is left uncommented as a reader exercise ;)
+
+# PORTAGE_ELOG_MAILFROM: you can set the from-address of logmails with this variable,
+#                        if unset mails are sent by "portage" (this default may fail
+#                        in some environments).
+#PORTAGE_ELOG_MAILFROM="portage@some.domain"
+
+# PORTAGE_ELOG_MAILSUBJECT: template string to be used as subject for logmails. The following
+#                           variables are expanded:
+#                               ${PACKAGE} - see description of PORTAGE_ELOG_COMMAND
+#                               ${HOST} - FQDN of the host portage is running on
+#PORTAGE_ELOG_MAILSUBJECT="package \${PACKAGE} merged on \${HOST} with notice"
Index: /vendor/portage/current/cnf/make.conf.alpha.diff
===================================================================
--- /vendor/portage/current/cnf/make.conf.alpha.diff	(revision 3419)
+++ /vendor/portage/current/cnf/make.conf.alpha.diff	(revision 3419)
@@ -0,0 +1,50 @@
+--- make.conf	2006-03-19 18:40:11.000000000 +0100
++++ make.conf.alpha	2006-03-19 18:26:21.000000000 +0100
+@@ -23,6 +23,17 @@
+ # Example:
+ #USE="X gtk gnome -alsa"
+ 
++# Host Setting
++# ============
++#
++# DO NOT CHANGE THIS SETTING UNLESS YOU ARE USING STAGE1!
++# The generic HOST setting on alpha is alpha-unknown-linux-gnu. If your machine
++# is an ev6 or ev67 based system you might want to use 
++# either alphaev6-unknown-linux-gnu or alphaev67-unknown-linux-gnu accordingly.
++#
++#CHOST="alphaev67-unknown-linux-gnu"
++CHOST="alpha-unknown-linux-gnu"
++
+ # Host and optimization settings 
+ # ==============================
+ #
+@@ -33,10 +44,18 @@
+ # package (and in some cases the libraries it uses) at default optimizations
+ # before reporting errors to developers.
+ #
+-# Please refer to the GCC manual for a list of possible values.
++# -mcpu=<cpu-type> means optimize code for the particular type of CPU. In 
++#                  difference to x86 for example -mcpu does break compatibility
++#                  to older cpu types in case of ev6 or higher.
++#                  On Alpha there is no -march= option in gcc-3.
+ #
+-#CFLAGS="-O2 -pipe"
++# CPU types supported in gcc-3.2 or higher: ev4, ev45, ev5, ev56, ev6, ev67
+ #
++# Decent examples:
++#
++#CFLAGS="-mcpu=ev67 -O3 -pipe "
++CFLAGS="-mcpu=ev5 -O3 -pipe "
++
+ # If you set a CFLAGS above, then this line will set your default C++ flags to
+ # the same settings.
+ #CXXFLAGS="${CFLAGS}"
+@@ -61,7 +80,7 @@
+ # DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+ # IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+ #
+-#ACCEPT_KEYWORDS="~arch"
++#ACCEPT_KEYWORDS="~alpha"
+ 
+ # Portage Directories
+ # ===================
Index: /vendor/portage/current/cnf/make.conf.amd64.diff
===================================================================
--- /vendor/portage/current/cnf/make.conf.amd64.diff	(revision 3419)
+++ /vendor/portage/current/cnf/make.conf.amd64.diff	(revision 3419)
@@ -0,0 +1,61 @@
+--- make.conf	2006-03-19 18:40:11.000000000 +0100
++++ make.conf.amd64	2006-03-19 18:26:21.000000000 +0100
+@@ -23,6 +23,11 @@
+ # Example:
+ #USE="X gtk gnome -alsa"
+ 
++# Host Setting
++# ============
++#
++CHOST="x86_64-pc-linux-gnu"
++
+ # Host and optimization settings 
+ # ==============================
+ #
+@@ -33,10 +38,35 @@
+ # package (and in some cases the libraries it uses) at default optimizations
+ # before reporting errors to developers.
+ #
+-# Please refer to the GCC manual for a list of possible values.
++# -mcpu=<cpu-type> means optimize code for the particular type of CPU without
++# breaking compatibility with other CPUs. GCC 3.4 has deprecated support for
++# -mcpu, so use -mtune instead if using this compiler.
++#
++# -march=<cpu-type> means to take full advantage of the ABI and instructions
++# for the particular CPU; this will break compatibility with older CPUs (for
++# example, -march=athlon-xp code will not run on a regular Athlon, and
++# -march=i686 code will not run on a Pentium Classic.)
++#
++# CPU types supported in gcc-3.2 and higher: athlon-xp, athlon-mp,
++# athlon-tbird, athlon, k6, k6-2, k6-3, i386, i486, i586 (Pentium), i686
++# (PentiumPro), pentium, pentium-mmx, pentiumpro, pentium2 (Celeron),
++# pentium3, and pentium4.
++#
++# Note that Gentoo Linux 1.4 and higher include at least gcc-3.2.
++#
++# amd64 CPU types supported in gcc-3.4: athlon64, opteron, k8
++# 
++# CRITICAL WARNINGS: ****************************************************** #
++# K6 markings are deceptive. Avoid setting -march for them. See Bug #24379. #
++# Pentium-M CPU's should not enable sse2 until at least gcc-3.4. Bug 50616. #
++# GCC 3.3 doesnt support an amd64 specific -march setting, use 3.4.         #
++# ************************************************************************* #
+ #
+-#CFLAGS="-O2 -pipe"
++# Decent examples:
+ #
++#CFLAGS="-mtune=k8 -O2 -pipe"
++#CFLAGS="-march=athlon64 -O2 -pipe"
++
+ # If you set a CFLAGS above, then this line will set your default C++ flags to
+ # the same settings.
+ #CXXFLAGS="${CFLAGS}"
+@@ -61,7 +91,7 @@
+ # DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+ # IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+ #
+-#ACCEPT_KEYWORDS="~arch"
++#ACCEPT_KEYWORDS="~amd64"
+ 
+ # Portage Directories
+ # ===================
Index: /vendor/portage/current/cnf/make.conf.arm.diff
===================================================================
--- /vendor/portage/current/cnf/make.conf.arm.diff	(revision 3419)
+++ /vendor/portage/current/cnf/make.conf.arm.diff	(revision 3419)
@@ -0,0 +1,50 @@
+--- make.conf	2006-03-19 18:40:11.000000000 +0100
++++ make.conf.arm	2006-03-19 18:26:21.000000000 +0100
+@@ -23,6 +23,19 @@
+ # Example:
+ #USE="X gtk gnome -alsa"
+ 
++# Host Setting
++# ============
++#
++# DO NOT CHANGE THIS SETTING UNLESS YOU ARE USING STAGE1!
++# It's very important you select the right CHOST from the start.  A wrong
++# CHOST could easily lead to weird errors either in compiling or running.
++#
++# Netwinder (or any StrongArm110): armv4l-unknown-linux-gnu
++# nslu2: armvbe-unknown-linux-gnu
++# Generic ARM: arm-unknown-linux-gnu
++#
++CHOST="armv4l-unknown-linux-gnu"
++
+ # Host and optimization settings 
+ # ==============================
+ #
+@@ -33,10 +46,24 @@
+ # package (and in some cases the libraries it uses) at default optimizations
+ # before reporting errors to developers.
+ #
+-# Please refer to the GCC manual for a list of possible values.
+-#
+-#CFLAGS="-O2 -pipe"
++# -mcpu=<cpu-type> means optimize code for the particular type of CPU without
++# breaking compatibility with other CPUs.
+ #
++# -march=<cpu-type> means to take full advantage of the ABI and instructions
++# for the particular CPU; this will break compatibility with older CPUs (for
++# example, -march=xscale code will not run on a StrongARM 11x0, and
++# -march=strongarm110 code will not run on a regular StrongARM).
++#
++# Don't use -O3.  Even -O2 may be risky in some cases.
++#
++# For a full listing of supported CPU models, please refer to the GCC website:
++# http://gcc.gnu.org/onlinedocs/gcc-3.3/gcc/ARM-Options.html
++#
++# Netwinder:
++#CFLAGS="-mcpu=strongarm110 -O2 -pipe"
++# NSLU2:
++#CFLAGS="-mcpu=armeb -O2 -pipe"
++
+ # If you set a CFLAGS above, then this line will set your default C++ flags to
+ # the same settings.
+ #CXXFLAGS="${CFLAGS}"
Index: /vendor/portage/current/cnf/make.conf.hppa.diff
===================================================================
--- /vendor/portage/current/cnf/make.conf.hppa.diff	(revision 3419)
+++ /vendor/portage/current/cnf/make.conf.hppa.diff	(revision 3419)
@@ -0,0 +1,71 @@
+--- make.conf	2006-03-19 18:40:11.000000000 +0100
++++ make.conf.hppa	2006-03-24 18:36:24.000000000 +0100
+@@ -23,6 +23,18 @@
+ # Example:
+ #USE="X gtk gnome -alsa"
+ 
++# Host Setting
++# ============
++#
++# DO NOT CHANGE THIS SETTING UNLESS YOU ARE USING STAGE1!
++# The generic CHOST value for hppa is hppa-unknown-linux-gnu.
++# But you might want to use hppa1.1-unknown-linux-gnu or hppa2.0-unknown-linux-gnu
++# according to your station.
++#
++CHOST="hppa-unknown-linux-gnu"
++#CHOST="hppa1.1-unknown-linux-gnu"
++#CHOST="hppa2.0-unknown-linux-gnu"
++
+ # Host and optimization settings 
+ # ==============================
+ #
+@@ -33,14 +45,38 @@
+ # package (and in some cases the libraries it uses) at default optimizations
+ # before reporting errors to developers.
+ #
+-# Please refer to the GCC manual for a list of possible values.
++# -march=<cpu-type> means to take full advantage of the ABI and instructions
++# for the particular CPU; this will break compatibility with older CPUs (for
++# example, -march=2.0 code will not run on a regular hppa1.1 station)
++#
++# -mschedule=cpu-type create schedule code according to the constraints for the machine
++# cpu-type.  The choices for cpu-type are 700 7100, 7100LC, 7200, and 8000.
++# Use 'cat /proc/cpuinfo' to know the right schedule for your hppa.
++# Note that you must use 7100LC for 7300LC.
++#
++# Architectures types supported in gcc-3.2 and higher: 1.0, 1.1 and 2.0
++# Note that 64bit userspace is not yet implemented.
+ #
+-#CFLAGS="-O2 -pipe"
++# Decent examples:
+ #
++
++# Use this one if you have a hppa1.1
++#CFLAGS="-march=1.1 -O2 -pipe -mschedule=7100LC"
++
++# Or this one if you have a hppa2.0
++# Note that -march=2.0 was unstable on some stations.
++# -march=1.0 will create problems too.
++#CFLAGS="-O2 -pipe -mschedule=8000"
++
++
+ # If you set a CFLAGS above, then this line will set your default C++ flags to
+ # the same settings.
+ #CXXFLAGS="${CFLAGS}"
+ 
++# Btw it's recommended to use this setting for stability.
++# There are still many bugs with higher level of optimisation.
++#CXXFLAGS="-O1 -pipe"
++
+ # Advanced Masking
+ # ================
+ #
+@@ -61,7 +97,7 @@
+ # DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+ # IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+ #
+-#ACCEPT_KEYWORDS="~arch"
++#ACCEPT_KEYWORDS="~hppa"
+ 
+ # Portage Directories
+ # ===================
Index: /vendor/portage/current/cnf/make.conf.ia64.diff
===================================================================
--- /vendor/portage/current/cnf/make.conf.ia64.diff	(revision 3419)
+++ /vendor/portage/current/cnf/make.conf.ia64.diff	(revision 3419)
@@ -0,0 +1,40 @@
+--- make.conf	2006-03-19 18:40:11.000000000 +0100
++++ make.conf.ia64	2006-03-19 18:26:21.000000000 +0100
+@@ -23,20 +23,18 @@
+ # Example:
+ #USE="X gtk gnome -alsa"
+ 
++# Host Setting
++# ============
++#
++# All Itanium systems should use this host setting:
++
++CHOST="ia64-unknown-linux-gnu"
++
+ # Host and optimization settings 
+ # ==============================
+ #
+-# For optimal performance, enable a CFLAGS setting appropriate for your CPU.
+-#
+-# Please note that if you experience strange issues with a package, it may be
+-# due to gcc's optimizations interacting in a strange way. Please test the
+-# package (and in some cases the libraries it uses) at default optimizations
+-# before reporting errors to developers.
+-#
+-# Please refer to the GCC manual for a list of possible values.
+-#
+ #CFLAGS="-O2 -pipe"
+-#
++
+ # If you set a CFLAGS above, then this line will set your default C++ flags to
+ # the same settings.
+ #CXXFLAGS="${CFLAGS}"
+@@ -61,7 +80,7 @@
+ # DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+ # IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+ #
+-#ACCEPT_KEYWORDS="~arch"
++#ACCEPT_KEYWORDS="~ia64"
+ 
+ # Portage Directories
+ # ===================
Index: /vendor/portage/current/cnf/make.conf.mips.diff
===================================================================
--- /vendor/portage/current/cnf/make.conf.mips.diff	(revision 3419)
+++ /vendor/portage/current/cnf/make.conf.mips.diff	(revision 3419)
@@ -0,0 +1,43 @@
+--- make.conf	2006-03-19 18:40:11.000000000 +0100
++++ make.conf.mips	2006-03-19 18:26:21.000000000 +0100
+@@ -23,6 +23,13 @@
+ # Example:
+ #USE="X gtk gnome -alsa"
+ 
++# Host Setting
++# ============
++#
++# All MIPS systems should use this host setting:
++
++CHOST="mips-unknown-linux-gnu"
++
+ # Host and optimization settings 
+ # ==============================
+ #
+@@ -33,10 +40,15 @@
+ # package (and in some cases the libraries it uses) at default optimizations
+ # before reporting errors to developers.
+ #
+-# Please refer to the GCC manual for a list of possible values.
++# -mcpu=<cpu-type> for MIPS systems selects the type of processor you want
++# to optimize your code for.   Code generated under those options will run best
++# on that processor, and may not run at all on others.
+ #
+-#CFLAGS="-O2 -pipe"
++# GCC 3.2 supports many mips processor types including: r2000, r3000, r3900, r4000, 
++# r4100, r4300, r4400, r4600, r4650, r5000, r6000, r8000 , orion
+ #
++#CFLAGS="-O2 -pipe"
++
+ # If you set a CFLAGS above, then this line will set your default C++ flags to
+ # the same settings.
+ #CXXFLAGS="${CFLAGS}"
+@@ -61,7 +73,7 @@
+ # DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+ # IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+ #
+-#ACCEPT_KEYWORDS="~arch"
++#ACCEPT_KEYWORDS="~mips"
+ 
+ # Portage Directories
+ # ===================
Index: /vendor/portage/current/cnf/make.conf.ppc.diff
===================================================================
--- /vendor/portage/current/cnf/make.conf.ppc.diff	(revision 3419)
+++ /vendor/portage/current/cnf/make.conf.ppc.diff	(revision 3419)
@@ -0,0 +1,87 @@
+--- make.conf	2006-03-19 18:40:11.000000000 +0100
++++ make.conf.ppc	2006-03-19 18:26:21.000000000 +0100
+@@ -23,6 +23,13 @@
+ # Example:
+ #USE="X gtk gnome -alsa"
+ 
++# Host Setting
++# ============
++#
++# All PowerPC systems should use this host setting:
++
++CHOST="powerpc-unknown-linux-gnu"
++
+ # Host and optimization settings 
+ # ==============================
+ #
+@@ -33,10 +40,56 @@
+ # package (and in some cases the libraries it uses) at default optimizations
+ # before reporting errors to developers.
+ #
+-# Please refer to the GCC manual for a list of possible values.
++# -mcpu=<cpu-type> for PowerPC systems selects the type of processor you want
++# to optimize your code for.   Code generated under those options will run best
++# on that processor, and may not run at all on others.
++#
++# GCC 3.4 supports many powerpc processor types including: 401, 403, 405,
++# 405fp, 440, 440fp, 505, 601, 602, 603, 603e, 604, 604e, 620, 630, 740, 7400,
++# 7450, 750, 801, 821, 823, 860, 970, 8540, common, ec603e, G3, G4, G5, power,
++# power2, power3, power4, power5, powerpc, powerpc64, rios, rios1, rios2, rsc,
++# and rs64a
++#
++# Recommended settings for GCC 3.4 only :
++#
++# -maltivec enables optional altivec support and should be used
++# only for G4 processors,  on GCC 3.2 or newer.  It also requires that you have
++# the alitvec option compiled into your kernel to take full advantage of this
++# feature.  Note: you should also include -mabi=altivec flag if using this 
++# option.
++#
++# The newer gcc has a stricter aliasing ruleset that makes type punned 
++# expression faulty compiled if -fstrict-aliasing is enabled.
++# That option is implied by -O2 -Os and -O3. Make SURE you don't have that
++# option enabled by adding -fno-strict-aliasing to your CFLAGS and CXXFLAGS
++#
++# Long term testing has shown that -O3 opts can be unreliable on G4's but work
++# on G3 series processors or earlier.
++#
++# The following is the suggested CFLAGS for a generic G4 cpu
++#
++#CFLAGS="-O2 -pipe -mcpu=G4 -maltivec -mabi=altivec -fno-strict-aliasing"
+ #
+-#CFLAGS="-O2 -pipe"
+ #
++# All non G4 PPC boxen should choose this next option.  It will work fine for
++# all G3 and pre machines.  (note it will not hurt pre G3 machines either to 
++# use this mcpu option as it is the default for gcc 3.2.x anyway)
++#
++#CFLAGS="-O3 -pipe -mcpu=G3 -fno-strict-aliasing"
++
++# Recommended settings for GCC 2.95.3 only (Gentoo 1.2 or older):
++#
++# PowerPC 750 > up: this works on G3's and G4s, gcc 2.95.3 doesn't make the
++# distinction between G3 and G4, so this is fine for all NewWorld machines, if
++# you use yaboot to boot you should select this option
++#
++#CFLAGS="-O2 -pipe -mcpu=750 -mpowerpc-gfxopt -mmultiple -mstring"
++#
++# This will run on all other processors, by building more generic code This is
++# safe for all PPC machines running gcc 2.95.3, and works for all OldWorld
++# machines - if you use BootX to boot you should select this option
++#CFLAGS="-O2 -pipe -mmultiple -mstring"
++
+ # If you set a CFLAGS above, then this line will set your default C++ flags to
+ # the same settings.
+ #CXXFLAGS="${CFLAGS}"
+@@ -61,7 +114,10 @@
+ # DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+ # IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+ #
+-#ACCEPT_KEYWORDS="~arch"
++# Note: this really shouldn't be enabled until _AFTER_ you bootstrap and emerge
++# system.  If you want the testing things update after these steps are completed.
++#
++#ACCEPT_KEYWORDS="~ppc"
+ 
+ # Portage Directories
+ # ===================
Index: /vendor/portage/current/cnf/make.conf.ppc64.diff
===================================================================
--- /vendor/portage/current/cnf/make.conf.ppc64.diff	(revision 3419)
+++ /vendor/portage/current/cnf/make.conf.ppc64.diff	(revision 3419)
@@ -0,0 +1,69 @@
+--- make.conf	2006-03-19 18:40:11.000000000 +0100
++++ make.conf.ppc64	2006-03-19 18:26:21.000000000 +0100
+@@ -23,6 +23,13 @@
+ # Example:
+ #USE="X gtk gnome -alsa"
+ 
++# Host Setting
++# ============
++#
++# All PowerPC64 systems should use this host setting:
++
++CHOST="powerpc64-unknown-linux-gnu"
++
+ # Host and optimization settings 
+ # ==============================
+ #
+@@ -33,9 +40,38 @@
+ # package (and in some cases the libraries it uses) at default optimizations
+ # before reporting errors to developers.
+ #
+-# Please refer to the GCC manual for a list of possible values.
++# -mtune=<cpu-type> for PowerPC64 systems instructs the gcc compiler that
++# it can use instruction scheduling specific for that type of processor
++# specified
++#
++# -mcpu=<cpu-type> for PowerPC64 systems selects the type of processor you want
++# to optimize your code for.   Code generated under those options will run best
++# on that processor.
++#
++# -mcpu=<cpu-type>  and -mtune=<cpu-type>  should both be specified
++#
++# GCC 3.x supports many ppc64 processor types including: power3, power4,
++# 970 (aka G5), and power5.
++#
++# RS64 processors should specify power3. 
++#
++# Additional options of interest:
++#
++# -maltivec enables optional altivec support and should be used
++# only for 970 processors.  It also requires that you have
++# the alitvec option compiled into your kernel to take full advantage of this
++# feature.  Note: you should also include -mabi=altivec flag if using this option.
+ #
+-#CFLAGS="-O2 -pipe"
++# -O3 for the most part seems ok but should be used with caution as
++# for instance app-editors/vim has problems if it is used. -O2 is a
++# good selection.
++#
++#Example CFLAGS setting
++#CFLAGS="-O2 -pipe -mcpu=970 -mtune=970 -maltivec -mabi=altivec"
++#
++#or
++#
++#CFLAGS="-O2 -pipe -mcpu=power3 -mtune=power3"
+ #
+ # If you set a CFLAGS above, then this line will set your default C++ flags to
+ # the same settings.
+@@ -61,7 +97,10 @@
+ # DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+ # IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+ #
+-#ACCEPT_KEYWORDS="~arch"
++# Note: this really shouldn't be enabled until _AFTER_ you bootstrap and emerge
++# system.  If you want the testing things update after these steps are completed.
++#
++#ACCEPT_KEYWORDS="ppc64"
+ 
+ # Portage Directories
+ # ===================
Index: /vendor/portage/current/cnf/make.conf.s390.diff
===================================================================
--- /vendor/portage/current/cnf/make.conf.s390.diff	(revision 3419)
+++ /vendor/portage/current/cnf/make.conf.s390.diff	(revision 3419)
@@ -0,0 +1,40 @@
+--- make.conf	2006-03-19 18:40:11.000000000 +0100
++++ make.conf.s390	2006-03-19 18:26:21.000000000 +0100
+@@ -23,20 +23,18 @@
+ # Example:
+ #USE="X gtk gnome -alsa"
+ 
++# Host Setting
++# ============
++#
++# All s390 systems should use this host setting:
++
++CHOST="s390-ibm-linux-gnu"
++
+ # Host and optimization settings 
+ # ==============================
+ #
+-# For optimal performance, enable a CFLAGS setting appropriate for your CPU.
+-#
+-# Please note that if you experience strange issues with a package, it may be
+-# due to gcc's optimizations interacting in a strange way. Please test the
+-# package (and in some cases the libraries it uses) at default optimizations
+-# before reporting errors to developers.
+-#
+-# Please refer to the GCC manual for a list of possible values.
+-#
+ #CFLAGS="-O2 -pipe"
+-#
++
+ # If you set a CFLAGS above, then this line will set your default C++ flags to
+ # the same settings.
+ #CXXFLAGS="${CFLAGS}"
+@@ -61,7 +80,7 @@
+ # DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+ # IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+ #
+-#ACCEPT_KEYWORDS="~arch"
++#ACCEPT_KEYWORDS="~s390"
+ 
+ # Portage Directories
+ # ===================
Index: /vendor/portage/current/cnf/make.conf.sh.diff
===================================================================
--- /vendor/portage/current/cnf/make.conf.sh.diff	(revision 3419)
+++ /vendor/portage/current/cnf/make.conf.sh.diff	(revision 3419)
@@ -0,0 +1,43 @@
+--- make.conf	2006-03-19 18:40:11.000000000 +0100
++++ make.conf.sh	2006-03-19 18:26:21.000000000 +0100
+@@ -23,6 +23,19 @@
+ # Example:
+ #USE="X gtk gnome -alsa"
+ 
++# Host Setting
++# ============
++#
++# DO NOT CHANGE THIS SETTING UNLESS YOU ARE USING STAGE1!
++# It's very important you select the right CHOST from the start.  A wrong
++# CHOST could easily lead to weird errors either in compiling or running.
++#
++# There are really only two choices right now:
++#   sh3-unknown-linux-gnu
++#   sh4-unknown-linux-gnu    (Dreamcast / LANTank)
++#
++CHOST="sh4-unknown-linux-gnu"
++
+ # Host and optimization settings 
+ # ==============================
+ #
+@@ -33,10 +46,17 @@
+ # package (and in some cases the libraries it uses) at default optimizations
+ # before reporting errors to developers.
+ #
+-# Please refer to the GCC manual for a list of possible values.
+-#
+-#CFLAGS="-O2 -pipe"
++# -m# optimize code for the particular type of CPU.  The number should match
++# your CHOST so if you are using "sh4-unknown-linux-gnu", you should have
++# -m4 below.
+ #
++# Don't use -O3.  Even -O2 may be risky in some cases.
++#
++# For a full listing of supported CPU models, please refer to the GCC website:
++# http://gcc.gnu.org/onlinedocs/gcc-3.3/gcc/SH-Options.html
++#
++#CFLAGS="-m4 -O2 -pipe"
++
+ # If you set a CFLAGS above, then this line will set your default C++ flags to
+ # the same settings.
+ #CXXFLAGS="${CFLAGS}"
Index: /vendor/portage/current/cnf/make.conf.sparc-fbsd.diff
===================================================================
--- /vendor/portage/current/cnf/make.conf.sparc-fbsd.diff	(revision 3419)
+++ /vendor/portage/current/cnf/make.conf.sparc-fbsd.diff	(revision 3419)
@@ -0,0 +1,35 @@
+--- make.conf	2006-10-16 17:06:32 +0100
++++ make.conf.sparc-fbsd	2006-10-16 17:09:22 +0100
+@@ -23,6 +23,13 @@
+ # Example:
+ #USE="X gtk gnome -alsa"
+ 
++# Host Setting
++# ============
++#
++# The version number at the end has to correspond to the version of the
++# profile and of freebsd-lib package.
++CHOST="sparc64-gentoo-freebsd6.2"
++
+ # Host and optimization settings 
+ # ==============================
+ #
+@@ -61,7 +68,7 @@
+ # DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+ # IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+ #
+-#ACCEPT_KEYWORDS="~arch"
++ACCEPT_KEYWORDS="~sparc-fbsd"
+ 
+ # Portage Directories
+ # ===================
+@@ -287,7 +294,8 @@
+ #  'notitles'    disables xterm titlebar updates (which contain status info). 
+ #  'parallel-fetch'
+ #                do fetching in parallel to compilation
+-#  'sandbox'     enables sandboxing when running emerge and ebuild.
++#  'sandbox'     enables sandboxing when running emerge and ebuild. Doesn't
++#                work on *BSD-based systems.
+ #  'strict'      causes portage to react strongly to conditions that are
+ #                potentially dangerous, like missing/incorrect Manifest files.
+ #  'userfetch'   when portage is run as root, drop privileges to
Index: /vendor/portage/current/cnf/make.conf.sparc.diff
===================================================================
--- /vendor/portage/current/cnf/make.conf.sparc.diff	(revision 3419)
+++ /vendor/portage/current/cnf/make.conf.sparc.diff	(revision 3419)
@@ -0,0 +1,66 @@
+--- make.conf	2006-03-19 18:40:11.000000000 +0100
++++ make.conf.sparc	2006-03-19 18:26:21.000000000 +0100
+@@ -23,6 +23,15 @@
+ # Example:
+ #USE="X gtk gnome -alsa"
+ 
++# Host Setting
++# ============
++# This should be left to the default value of sparc-unknown-linux-gnu unless
++# you are absolutely certain of the consequences.  In addition to potentially
++# destroying your system, you will recieve no support and your bugs will be 
++# marked INVALID if you change this.
++#
++# CHOST="sparc-unknown-linux-gnu"
++
+ # Host and optimization settings 
+ # ==============================
+ #
+@@ -33,10 +42,34 @@
+ # package (and in some cases the libraries it uses) at default optimizations
+ # before reporting errors to developers.
+ #
+-# Please refer to the GCC manual for a list of possible values.
+-#
+-#CFLAGS="-O2 -pipe"
+-#
++# Sparc specific cpu optimizatiobn flags can be found here:
++# http://gcc.gnu.org/onlinedocs/gcc-3.3/gcc/SPARC-Options.html#SPARC%20Options
++# 
++# -mcpu=<cpu-type> means optimize code for the particular type of CPU without
++# breaking compatibility with other CPUs.
++#
++# -mtune=<cpu-type> set the instruction scheduling parameters for machine, but
++# do not set the instruction set or register set.
++#
++# Here is a list of each supported architecture and their supported
++# implementations:
++#
++# gcc-3.2 and higher:
++#    v7:             cypress
++#    v8:             supersparc, hypersparc
++#    sparclite:      f930, f934, sparclite86x
++#    sparclet:       tsc701
++#    v9:             ultrasparc
++#
++# Additionally in gcc-3.3 and higher:
++#    v9:             ultrasparc3
++#
++# Decent examples:
++#
++#CFLAGS="-mcpu=supersparc -O3 -pipe"
++#CFLAGS="-mcpu=ultrasparc -O3 -pipe"
++#CFLAGS="-mcpu=v8 -mtune=v9 -O2 -pipe"
++
+ # If you set a CFLAGS above, then this line will set your default C++ flags to
+ # the same settings.
+ #CXXFLAGS="${CFLAGS}"
+@@ -61,7 +94,7 @@
+ # DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+ # IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+ #
+-#ACCEPT_KEYWORDS="~arch"
++#ACCEPT_KEYWORDS="~sparc"
+ 
+ # Portage Directories
+ # ===================
Index: /vendor/portage/current/cnf/make.conf.x86-fbsd.diff
===================================================================
--- /vendor/portage/current/cnf/make.conf.x86-fbsd.diff	(revision 3419)
+++ /vendor/portage/current/cnf/make.conf.x86-fbsd.diff	(revision 3419)
@@ -0,0 +1,74 @@
+--- make.conf	2006-03-19 18:40:11.000000000 +0100
++++ make.conf.x86-fbsd	2006-03-19 18:26:21.000000000 +0100
+@@ -23,6 +23,16 @@
+ # Example:
+ #USE="X gtk gnome -alsa"
+ 
++# Host Setting
++# ============
++#
++# Change this line as appropriate (i686, i586, i486 or i386).
++# All modern systems (even Athlons) should use "i686-pc-linux-gnu".
++# All K6's are i586.
++# The version number at the end has to correspond to the version of the
++# profile and of freebsd-lib package.
++CHOST="i686-gentoo-freebsd6.1"
++
+ # Host and optimization settings 
+ # ==============================
+ #
+@@ -33,10 +42,34 @@
+ # package (and in some cases the libraries it uses) at default optimizations
+ # before reporting errors to developers.
+ #
+-# Please refer to the GCC manual for a list of possible values.
++# -mtune=<cpu-type> means optimize code for the particular type of CPU without
++# breaking compatibility with other CPUs.
++#
++# -march=<cpu-type> means to take full advantage of the ABI and instructions
++# for the particular CPU; this will break compatibility with older CPUs (for
++# example, -march=athlon-xp code will not run on a regular Athlon, and
++# -march=i686 code will not run on a Pentium Classic.
++#
++# CPU types supported in gcc-3.2 and higher: athlon-xp, athlon-mp,
++# athlon-tbird, athlon, k6, k6-2, k6-3, i386, i486, i586 (Pentium), i686
++# (PentiumPro), pentium, pentium-mmx, pentiumpro, pentium2 (Celeron),
++# pentium3, and pentium4.
++#
++# Note that Gentoo Linux 1.4 and higher include at least gcc-3.2.
++# 
++# CPU types supported in gcc-2.95*: k6, i386, i486, i586 (Pentium), i686
++# (Pentium Pro), pentium, pentiumpro Gentoo Linux 1.2 and below use gcc-2.95*
++#
++# CRITICAL WARNINGS: ****************************************************** #
++# K6 markings are deceptive. Avoid setting -march for them. See Bug #24379. #
++# Pentium-M CPU's should not enable sse2 until at least gcc-3.4. Bug 50616. #
++# ************************************************************************* #
+ #
+-#CFLAGS="-O2 -pipe"
++# Decent examples:
+ #
++#CFLAGS="-mtune=athlon-xp -O3 -pipe"
++#CFLAGS="-march=pentium3 -O3 -pipe"
++
+ # If you set a CFLAGS above, then this line will set your default C++ flags to
+ # the same settings.
+ #CXXFLAGS="${CFLAGS}"
+@@ -61,7 +80,7 @@
+ # DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+ # IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+ #
+-#ACCEPT_KEYWORDS="~arch"
++ACCEPT_KEYWORDS="~x86-fbsd"
+ 
+ # Portage Directories
+ # ===================
+@@ -268,7 +289,8 @@
+ #  'notitles'    disables xterm titlebar updates (which contain status info). 
+ #  'parallel-fetch'
+ #                do fetching in parallel to compilation
+-#  'sandbox'     enables sandboxing when running emerge and ebuild.
++#  'sandbox'     enables sandboxing when running emerge and ebuild. Doesn't 
++#                work on *BSD-based systems.
+ #  'strict'      causes portage to react strongly to conditions that are
+ #                potentially dangerous, like missing/incorrect Manifest files.
Index: /vendor/portage/current/cnf/make.conf.x86.diff
===================================================================
--- /vendor/portage/current/cnf/make.conf.x86.diff	(revision 3419)
+++ /vendor/portage/current/cnf/make.conf.x86.diff	(revision 3419)
@@ -0,0 +1,96 @@
+--- make.conf	2007-01-10 03:22:07.410548112 +0100
++++ make.conf.x86	2007-01-10 03:22:13.206910362 +0100
+@@ -23,6 +23,15 @@
+ # Example:
+ #USE="X gtk gnome -alsa"
+ 
++# Host Setting
++# ============
++#
++# DO NOT CHANGE THIS SETTING UNLESS YOU ARE USING STAGE1!
++# Change this line as appropriate (i686, i586, i486 or i386).
++# All modern systems (even Athlons) should use "i686-pc-linux-gnu".
++# All K6's are i586.
++CHOST="i686-pc-linux-gnu"
++
+ # Host and optimization settings 
+ # ==============================
+ #
+@@ -33,10 +42,65 @@
+ # package (and in some cases the libraries it uses) at default optimizations
+ # before reporting errors to developers.
+ #
+-# Please refer to the GCC manual for a list of possible values.
+-#
+-#CFLAGS="-O2 -pipe"
++# -mcpu=<cpu-type> means optimize code for the particular type of CPU without
++# breaking compatibility with other CPUs.
+ #
++# -march=<cpu-type> means to take full advantage of the ABI and instructions
++# for the particular CPU; this will break compatibility with older CPUs (for
++# example, -march=athlon-xp code will not run on a regular Athlon, and
++# -march=i686 code will not run on a Pentium Classic.
++#
++# CPU types supported by gcc version:
++# (Higher versions include the targets from older ones,
++# those listed on the same line are equivalent.)
++# === >=gcc-2.95
++# i386			Original Intel's i386.
++# i486			Intel's i486. (No scheduling implemented.)
++# i586, pentium	Intel Pentium with no MMX support.
++# pentium-mmx	Intel PentiumMMX based on Pentium core with MMX.
++# i686, pentiumpro	Intel PentiumPro.
++# === >=gcc-3.2
++# k6			AMD K6 with MMX.
++# k6-2, k6-3	AMD K6 with MMX and 3dNOW!.
++# pentium2		Intel Pentium2 based on PentiumPro with MMX.
++# pentium3		Intel Pentium3 based on PentiumPro with MMX and SSE.
++# pentium4		Intel Pentium4 with MMX, SSE and SSE2.
++# athlon, athlon-tbird	AMD Athlon with MMX, 3dNOW!, enhanced 3dNOW!
++#				and SSE prefetch.
++# athlon-4, athlon-xp, athlon-mp	AMD Athlon with MMX, 3dNOW!, enhanced
++#				3dNOW! and full SSE.
++# === >=gcc-3.3
++# winchip-c6	IDT Winchip C6, i486 with MMX.
++# winchip2		IDT Winchip2, i486 MMX and 3dNOW!.
++# c3			Via C3 with MMX and 3dNOW! (No scheduling implemented.)
++# === >=gcc-4.1
++# c3-2			Via C3-2 with MMX and SSE. (No scheduling implemented.)
++# pentium-m		Low power version of Intel Pentium3 with MMX, SSE, SSE2.
++#				Used by Centrino notebooks.
++# prescott		Intel Pentium4 with MMX, SSE, SSE2 and SSE3.
++# nocona		Intel Pentium4 with 64-bit extensions, MMX, SSE, SSE2
++#				and SSE3.
++# k8, opteron, athlon64, athlon-fx	AMD K8 core based CPUs with x86-64.
++#				(This supersets MMX, SSE, SSE2, 3dNOW!, enhanced 3dNOW! and
++#				64-bit extensions.)
++#
++# Gentoo Linux 1.2 and below used gcc-2.95*
++# Gentoo Linux 1.4 and 2004.* had gcc-3.2
++# Gentoo Linux 2005.1 through 2006.0 use gcc-3.3
++# Gentoo Linux 2006.1 has gcc-4.1
++# 
++#
++# CRITICAL WARNINGS: ****************************************************** #
++# K6 markings are deceptive. Avoid setting -march for them. See Bug #24379. #
++# Pentium-M CPU's should not enable sse2 until at least gcc-3.4. Bug 50616. #
++# ************************************************************************* #
++#
++# NOTE: the -On optimization levels are set with the letter O, not -0 (zero).
++#
++# Decent examples:
++#CFLAGS="-mcpu=athlon-xp -O3 -pipe"
++#CFLAGS="-march=pentium3 -O3 -pipe"
++
+ # If you set a CFLAGS above, then this line will set your default C++ flags to
+ # the same settings.
+ #CXXFLAGS="${CFLAGS}"
+@@ -61,7 +125,7 @@
+ # DO NOT PUT ANYTHING BUT YOUR SPECIFIC ~ARCHITECTURE IN THE LIST.
+ # IF YOU ARE UNSURE OF YOUR ARCH, OR THE IMPLICATIONS, DO NOT MODIFY THIS.
+ #
+-#ACCEPT_KEYWORDS="~arch"
++#ACCEPT_KEYWORDS="~x86"
+ 
+ # Portage Directories
+ # ===================
Index: /vendor/portage/current/cnf/make.globals
===================================================================
--- /vendor/portage/current/cnf/make.globals	(revision 3419)
+++ /vendor/portage/current/cnf/make.globals	(revision 3419)
@@ -0,0 +1,87 @@
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: make.globals 4734 2006-10-17 04:31:10Z zmedico $
+# System-wide defaults for the Portage system
+
+#            *****************************
+#            **  DO NOT EDIT THIS FILE  **
+# ***************************************************
+# **** CHANGES TO make.conf *OVERRIDE* THIS FILE ****
+# ***************************************************
+# ** Incremental Variables Accumulate Across Files **
+# **  USE, CONFIG_*, and FEATURES are incremental  **
+# ***************************************************
+
+
+# Default rsync mirror
+SYNC="rsync://rsync.gentoo.org/gentoo-portage"
+
+# Default distfiles mirrors
+GENTOO_MIRRORS="http://distfiles.gentoo.org http://distro.ibiblio.org/pub/linux/distributions/gentoo"
+
+# Repository Paths
+PORTDIR=/usr/portage
+DISTDIR=/usr/portage/distfiles
+PKGDIR=/usr/portage/packages
+RPMDIR=/usr/portage/rpm
+
+# Temporary build directory
+PORTAGE_TMPDIR=/var/tmp
+
+# Fetching command (5 tries, passive ftp for firewall compatibility)
+FETCHCOMMAND="/usr/bin/wget -t 5 -T 60 --passive-ftp -P \${DISTDIR} \${URI}"
+RESUMECOMMAND="/usr/bin/wget -c -t 5 -T 60 --passive-ftp -P \${DISTDIR} \${URI}"
+
+# Default user options
+FEATURES="sandbox distlocks metadata-transfer"
+
+# Default chunksize for binhost comms
+PORTAGE_BINHOST_CHUNKSIZE="3000"
+
+# By default wait 5 secs before cleaning a package
+CLEAN_DELAY="5"
+
+# By default wait 10 secs on an important warning
+EMERGE_WARNING_DELAY="10"
+
+# Automatically clean installed packages after they are updated.
+# This option will be removed and forced to yes.
+AUTOCLEAN="yes"
+
+# Number of times 'emerge --sync' will run before giving up.
+PORTAGE_RSYNC_RETRIES="3"
+
+# Number of seconds rsync will wait before timing out.
+#RSYNC_TIMEOUT="180"
+
+PORTAGE_RSYNC_OPTS="--recursive --links --safe-links --perms --times --compress --force --whole-file --delete --delete-after --stats --timeout=180 --exclude=/distfiles --exclude=/local --exclude=/packages --filter=H_**/files/digest-*"
+
+# Minimal CONFIG_PROTECT
+CONFIG_PROTECT="/etc"
+CONFIG_PROTECT_MASK="/etc/env.d"
+
+# Disable auto-use
+USE_ORDER="env:pkg:conf:defaults:pkginternal"
+
+# Default ownership of installed files.
+PORTAGE_INST_UID="0"
+PORTAGE_INST_GID="0"
+
+# Mode bits for ${WORKDIR} (see ebuild.5).
+PORTAGE_WORKDIR_MODE="0700"
+
+# Some defaults for elog
+PORTAGE_ELOG_CLASSES="log warn error"
+
+PORTAGE_ELOG_MAILURI="root"
+PORTAGE_ELOG_MAILSUBJECT="[portage] ebuild log for \${PACKAGE} on \${HOST}"
+PORTAGE_ELOG_MAILFROM="portage"
+
+#            *****************************
+#            **  DO NOT EDIT THIS FILE  **
+# ***************************************************
+# **** CHANGES TO make.conf *OVERRIDE* THIS FILE ****
+# ***************************************************
+# ** Incremental Variables Accumulate Across Files **
+# **  USE, CONFIG_*, and FEATURES are incremental  **
+# ***************************************************
Index: /vendor/portage/current/man/dispatch-conf.1
===================================================================
--- /vendor/portage/current/man/dispatch-conf.1	(revision 3419)
+++ /vendor/portage/current/man/dispatch-conf.1	(revision 3419)
@@ -0,0 +1,91 @@
+.TH "DISPATCH-CONF" "1" "Dec 2005" "Portage 2.1" "Portage"
+.SH NAME
+dispatch-conf \- Sanely update configuration files after emerging new packages
+.SH SYNOPSIS
+.B dispatch-conf
+.SH DESCRIPTION
+.I dispatch-conf
+is designed to be run after merging new packages in order to see if
+there are updates to the configuration files.  If a new
+configuration file will overwrite an old one, 
+.I dispatch-conf 
+will prompt the user for a decision about how to resolve the
+discrepancy.  
+Advantages of 
+.I dispatch-conf
+include easy rollback (changes to config files are stored either using
+patches or rcs) and the ability to automatically update config files
+that the user has never modified or 
+that differ from the current version only in CVS cruft or white space.
+
+.I dispatch-conf
+will check all directories in the \fICONFIG_PROTECT\fR variable.  All
+config files found in \fICONFIG_PROTECT_MASK\fR will automatically be
+updated for you by \fIdispatch-conf\fR.  See \fBmake.conf\fR(5) for more
+information.
+.SH OPTIONS
+.TP
+None.
+.SH USAGE
+.I dispatch-conf
+must be run as root, since the config files to be replaced are generally
+owned by root.  Before running
+.I dispatch-conf
+for the first time the settings in 
+.B /etc/dispatch-conf.conf
+should be edited and the archive directory specified in 
+\fI/etc/dispatch-conf.conf\fR will need to be created.  All changes to
+config files will be saved in the archive directory either as patches
+or using rcs, making restoration to an earlier version rather simple.
+
+When dispatch-conf finds a config file that has a new update the user 
+is provided
+with a menu of options for how to handle the update:
+.TP
+.B u
+Update (replace) the current config file with the new config file and continue.
+.TP
+.B z
+Zap (delete) the new config file and continue.
+.TP
+.B n
+Skip to the next config file, leaving both the original config file and any
+\fICONFIG_PROTECT\fRed files.
+.TP
+.B e
+Edit the new config file, using the editor defined in \fI$EDITOR\fR.
+.TP
+.B m
+Interactively merge the current and new config files.
+.TP
+.B l
+Look at the differences between the pre-merged and merged config files.
+.TP
+.B t
+Toggle between the merged and pre-merged config files (in terms of which
+should be installed using the 
+.Qt u
+command).
+.TP
+.B h
+Display a help screen.
+.TP
+.B q
+Quit
+.I dispatch-conf.
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH AUTHORS
+.nf
+Jeremy Wohl
+Karl Trygve Kalleberg <karltk@gentoo.org>
+Mike Frysinger <vapier@gentoo.org>
+Grant Goodyear <g2boojum@gentoo.org>
+.fi
+.SH "FILES"
+.TP
+.B /etc/dispatch-conf.conf
+Configuration settings for \fIdispatch-conf\fR are stored here.
+.SH "SEE ALSO"
+.BR make.conf (5),
+.BR etc-update (1)
Index: /vendor/portage/current/man/ebuild.1
===================================================================
--- /vendor/portage/current/man/ebuild.1	(revision 3419)
+++ /vendor/portage/current/man/ebuild.1	(revision 3419)
@@ -0,0 +1,191 @@
+.TH "EBUILD" "1" "Dec 2005" "Portage 2.1" "Portage"
+.SH "NAME"
+ebuild \- a low level interface to the Portage system
+.SH "SYNOPSIS"
+.B ebuild
+.I file command [command]\fR...
+.SH "DESCRIPTION"
+The ebuild program is a direct interface to the Portage system. It
+allows for direct action upon an ebuild with specific subcommands or
+groups of commands to perform in a specific ebuild's context and
+functions.  Accepting an ebuild script and one or more commands
+as arguments, the ebuild program parses the ebuild script and
+executes the specified commands.  Commands exist to fetch sources,
+unpack sources, compile sources, install object files into a temporary
+directory "image", merge the image to the local filesystem, create a
+bzipped tarball package out of the image, and more.
+.SH "FILE"
+This must be a valid ebuild script.  For further information read
+\fBebuild\fR(5).
+.SH "COMMANDS"
+By default, portage will execute all the functions in order up to the
+one actually specified.  For example, simply issuing the command \fBcompile\fR
+will trigger the functions before it to also be run (such as \fBsetup\fR
+and \fBunpack\fR).  If you wish to only have the specified command run, then
+you should use the \fInoauto\fR option in the \fBFEATURES\fR environment
+variable.  See the \fBmake.conf\fR(5) man page for more information.
+
+.TP
+.BR help
+Shows a condensed form of this man page along with a lot of package
+specific information.
+.TP
+.BR setup
+Runs all package-specific setup actions and exotic system checks.
+.TP
+.BR clean
+Cleans the temporary build directory that Portage has created for
+this particular ebuild file.  The temporary build directory normally
+contains the extracted source files as well as a possible
+"install image" (all the files that will be merged to the local
+filesystem or stored in a package).  The location of the build
+directory is set by the BUILD_PREFIX variable.  For information
+on what this variable is, run \fIemerge [\-v] info\fR, or to override
+this variable, see \fBmake.conf\fR(5).
+
+Note: Portage cleans up almost everything after a package has been
+successfully merged unless FEATURES contains 'noclean'.  Adding noclean
+to FEATURES will cause a lot of files to remain and will consume large
+amounts of space, very quickly.  It is not recommended to leave this on,
+unless you have use for the sources post\-merge.  Optionally, one may
+manually clean these files with \fIrm \-rf /var/tmp/portage\fR.
+.TP
+.BR fetch
+Checks to see if all the sources specified in SRC_URI are available in
+DISTDIR (see \fBmake.conf\fR(5) for more information) and have a valid
+md5 checksum.  If the sources aren't available, an attempt is made to
+download them from the locations specified in SRC_URI.  If multiple
+download locations are listed for a particular file, Portage pings
+each location to see which location is closer. (May not be true
+presently.)  The Gentoo Linux mirrors defined by GENTOO_MIRRORS is
+always considered first.  If for some reason the current or
+just\-downloaded sources' md5 digests don't match those recorded
+in files/digest\-[package]\-[version\-rev], a warning is printed
+and ebuild exits with an error code of 1.
+.TP
+.BR digest
+Creates a digest file for the package in
+/usr/portage/[category]/[package]/files/.  This digest file lists the
+md5sums of all the files found in the SRC_URI.  If the fetched source
+of the package is corrupt/bogus in some way, the md5sum will catch this.
+.TP
+.BR manifest
+Updates the manifest file for the package.  This performs the second half
+of the digest command, creating md5sums for the files in the files
+directory as well as the ebuild.
+.TP
+.BR unpack
+Extracts the sources to a subdirectory in the \fIbuild directory\fR
+(BUILD_PREFIX) by running the \fIsrc_unpack()\fR function in the ebuild
+file.  If no src_unpack() function has been specified, a default
+src_unpack() function is used that extracts all the files specified in
+SRC_URI.  The sources are normally extracted to
+${BUILD_PREFIX}/[package]\-[version\-rev]/work.  This particular directory
+can be referenced by using the ${WORKDIR} variable.
+
+If you're creating an ebuild, you'll want to make sure that the S
+(source directory) variable defined at the top of your ebuild script
+points to the directory that contains your extracted sources.  This
+directory is defined by default to be ${WORKDIR}/${P}, so it is not
+often required.  The src_unpack() function is also responsible for
+making the appropriate patches to the sources so that they're ready
+for compilation.
+.TP
+.BR compile
+Compiles the extracted sources by running the \fIsrc_compile()\fR
+function specified in the ebuild file.  When src_compile() starts, the
+current working directory will be set to ${S}.  When src_compile()
+completes, the sources should be fully compiled.
+.TP
+.BR test
+Runs package-specific test cases to verify that everything was built 
+properly.
+.TP
+.BR preinst
+Runs package-specific actions that need to be done before the package
+is installed into the live filesystem.
+.TP
+.BR install
+Installs the package to the temporary \fIinstall directory\fR by running
+the \fIsrc_install()\fR function.  When completed, the
+\fIinstall directory\fR (${BUILD_PREFIX}/[package]\-[version\-rev]/image)
+will contain all the files that should either be merged to the local
+filesystem or included in a binary package.
+.TP
+.BR postinst
+Runs package-specific actions that need to be done after the package
+is installed into the live filesystem.  Usually helpful messages are
+shown here.
+.TP
+.BR qmerge
+This function installs all the files in the \fIinstall directory\fR
+to the live filesystem.  The process works as follows: first, the
+\fIpkg_preinst()\fR function (if specified) is run.  Then, the files
+are merged into the live filesystem, and the installed files' md5
+digests are recorded in
+\fI/var/db/pkg/${CATEGORY}/${PN}\-${PVR}/CONTENTS\fR.  After
+all the files have been merged, the \fIpkg_postinst()\fR function
+(if specified) is executed.
+.TP
+.BR merge
+Normally, to merge an ebuild, you need to \fIfetch\fR, \fIunpack\fR,
+\fIcompile\fR, \fIinstall\fR and \fIqmerge\fR.  If you're simply
+interested in merging the ebuild, you can use this command, which
+will perform all these steps for you, stopping along the way if a
+particular step doesn't complete successfully.
+.TP
+.BR unmerge
+This function first executes the \fIpkg_prerm()\fR function (if specified).
+Then it removes all files from the live filesystem that have a valid md5
+checksum and mtime in the package contents file.  Any empty directories
+are recursively removed.  Finally, it runs \fIpkg_postrm()\fR function (if
+specified).  It is safe to merge a new version of a package first and
+then unmerge the old one.  In fact, this is the recommended package
+upgrade method.
+.TP
+.BR prerm
+Runs package-specific actions that need to be executed before the package is
+removed from the filesystem.  See also \fIunmerge\fR.
+.TP
+.BR postrm
+Runs package-specific actions that need to be executed after the package is
+removed from the filesystem.  See also \fIunmerge\fR.
+.TP
+.BR config
+Runs package-specific actions that need to be executed after the emerge
+process has completed.  This usually entails setup of configuration files
+or other similar setups that the user may wish to run.
+.TP
+.BR package
+This command is a lot like the \fImerge\fR command, except that after
+fetching, unpacking, compiling and installing, a .tbz2 binary package
+tarball is created and stored in  ${PKGDIR}/All (${PKGDIR} defaults to
+/usr/portage/packages).  A symbolic link is created in
+${PKGDIR}/${CATEGORY} that points to the package in ${PKGDIR}/All.
+.TP
+.BR rpm
+Builds a RedHat RPM package from the files in the temporary
+\fIinstall directory\fR.  At the moment, the ebuild's dependency
+information is not incorporated into the RPM.
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "AUTHORS"
+.nf
+Achim Gottinger <achim@gentoo.org>
+Daniel Robbins <drobbins@gentoo.org>
+Nicholas Jones <carpaski@gentoo.org>
+Mike Frysinger <vapier@gentoo.org>
+.fi
+.SH "FILES"
+.TP
+\fB/etc/make.conf\fR 
+Contains variables for the build\-process and overwrites those
+in make.globals.
+.SH "SEE ALSO"
+.BR emerge (1),
+.BR ebuild (5),
+.BR make.conf (5)
+.TP
+The \fI/usr/sbin/ebuild.sh\fR script. 
+.TP
+The helper apps in \fI/usr/lib/portage/bin\fR.
Index: /vendor/portage/current/man/ebuild.5
===================================================================
--- /vendor/portage/current/man/ebuild.5	(revision 3419)
+++ /vendor/portage/current/man/ebuild.5	(revision 3419)
@@ -0,0 +1,884 @@
+.TH "EBUILD" "5" "Jan 2007" "Portage 2.1.2" "Portage"
+.SH "NAME"
+ebuild \- the internal format, variables, and functions in an ebuild script
+.SH "DESCRIPTION"
+The
+.BR ebuild (1)
+program accepts a single ebuild script as an argument.  This script
+contains variables and commands that specify how to download, unpack,
+patch, compile, install and merge a particular software package from
+its original sources.  In addition to all of this, the ebuild script
+can also contain pre/post install/remove commands, as required.  All
+ebuild scripts are written in bash.
+.SH "EXAMPLES"
+Here's a simple example ebuild:
+
+.DS
+.nf
+# Copyright 1999\-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+inherit some_eclass another_eclass
+
+DESCRIPTION="Super\-useful stream editor (sed)"
+HOMEPAGE="http://www.gnu.org/software/sed/sed.html"
+SRC_URI="ftp://alpha.gnu.org/pub/gnu/sed/${P}.tar.gz"
+
+LICENSE="GPL\-2"
+SLOT="0"
+KEYWORDS="~x86"
+IUSE=""
+
+RDEPEND=""
+DEPEND="nls? ( sys-devel/gettext )"
+
+src_compile() {
+	econf \\
+		\-\-bindir=/bin \\
+		|| die "could not configure"
+	emake || die "emake failed"
+}
+
+src_install() {
+	emake install DESTDIR="${D}" || die "Install failed"
+	dodoc NEWS README* THANKS AUTHORS BUGS ChangeLog
+}
+.fi
+.SH "VARIABLES"
+.TP
+.B MISC USAGE NOTES
+\- All variables defined in \fBmake.conf\fR(5) are available for use in
+ebuilds (such as the PORTAGE* and PORTDIR* variables)
+.br
+\- When assigning values to variables in ebuilds, you \fBcannot have a
+space\fR between the variable name and the equal sign.
+.TP
+.B P
+This variable contains the package name without the ebuild revision.
+This variable must NEVER be modified.
+.br
+\fBxfree\-4.2.1\-r2.ebuild\fR \-\-> \fB$P\fR=='\fIxfree\-4.2.1\fR'
+.TP
+.B PN
+Contains the name of the script without the version number.
+.br
+\fBxfree\-4.2.1\-r2.ebuild\fR \-\-> \fB$PN\fR=='\fIxfree\fR'
+.TP
+.B PV
+Contains the version number without the revision.
+.br
+\fBxfree\-4.2.1\-r2.ebuild\fR \-\-> \fB$PV\fR=='\fI4.2.1\fR'
+.TP
+.B PR
+Contains the revision number or 'r0' if no revision number exists.
+.br
+\fBxfree\-4.2.1\-r2.ebuild\fR \-\-> \fB$PR\fR=='\fIr2\fR'
+.TP
+.B PVR
+Contains the version number with the revision.
+.br
+\fBxfree\-4.2.1\-r2.ebuild\fR \-\-> \fB$PVR\fR=='\fI4.2.1\-r2\fR'
+.TP
+.B PF
+Contains the full package name \fI[PN]\-[PVR]\fR
+.br
+\fBxfree\-4.2.1\-r2.ebuild\fR \-\-> \fB$PF\fR=='\fIxfree\-4.2.1\-r2\fR'
+.TP
+.B CATEGORY
+Contains the package category name.
+.TP
+.B A
+Contains all source files required for the package.  This variable must
+not be defined. It is autogenerated from the \fISRC_URI\fR variable.
+.TP
+\fBWORKDIR\fR = \fI"${PORTAGE_TMPDIR}/portage/${CATEGORY}/${PF}/work"\fR
+Contains the path to the package build root.  Do not modify this variable.
+.TP
+\fBFILESDIR\fR = \fI"${PORTDIR}/${CATEGORY}/${PN}/files"\fR
+Contains the path to the 'files' sub folder in the package specific
+location in the portage tree.  Do not modify this variable.
+.TP
+\fBS\fR = \fI"${WORKDIR}/${P}"\fR
+Contains the path to the temporary \fIbuild directory\fR.  This variable
+is used by the functions \fIsrc_compile\fR and \fIsrc_install\fR.  Both
+are executed with \fIS\fR as the current directory.  This variable may
+be modified to match the extraction directory of a tarball for the package.
+.TP
+\fBT\fR = \fI"${PORTAGE_TMPDIR}/portage/${CATEGORY}/${PF}/temp"\fR
+Contains the path to a \fItemporary directory\fR.  You may use this for
+whatever you like.
+.TP
+\fBD\fR = \fI"${PORTAGE_TMPDIR}/portage/${CATEGORY}/${PF}/image"\fR
+Contains the path to the temporary \fIinstall directory\fR.  Every write
+operation that does not involve the helper tools and functions (found below)
+should be prefixed with ${D}.  Do not modify this variable.
+.TP
+.B PORTAGE_LOG_FILE
+Contains the path of the build log. If \fBPORT_LOGDIR\fR variable is unset then
+\fBPORTAGE_LOG_FILE\fR=\fB"${T}/build.log"\fR.
+.TP
+\fBROOT\fR = \fI"/"\fR
+Contains the path that portage should use as the root of the live filesystem.
+When packages wish to make changes to the live filesystem, they should do so in
+the tree prefixed by ${ROOT}.  Do not modify this variable.
+.TP
+\fBDESCRIPTION\fR = \fI"A happy little package"\fR
+Should contain a short description of the package.
+.TP
+\fBSRC_URI\fR = \fI"http://happy.com/little/${P}.tar.gz"\fR
+Contains a list of URI's for the required source files.  It can contain
+multiple URI's for a single source file.  The list is processed in order
+if the file was not found on any of the \fIGENTOO_MIRRORS\fR.
+.TP
+\fBHOMEPAGE\fR = \fI"http://happy.com/"\fR
+Should contain a list of URL's for the sources main sites and other further
+package dependent information.
+.TP
+\fBKEYWORDS\fR = \fI[\-~][x86,ppc,sparc,mips,alpha,arm,hppa]\fR
+Should contain appropriate list of arches that the ebuild is know to
+work/not work.  By default if you do not know if an ebuild runs under
+a particular arch simply omit that KEYWORD.  If the ebuild will not
+work on that arch include it as \-ppc for example.  If the ebuild is
+being submitted for inclusion, it must have ~arch set for architectures
+where it has been PROVEN TO WORK.  (Packages KEYWORDed this way may be
+unmasked for testing by setting ACCEPT_KEYWORDS="~arch" on the command
+line, or in \fBmake.conf\fR(5)) For an authoritative list please review
+/usr/portage/profiles/arch.list.  Please keep this list in alphabetical order.
+.TP
+\fBSLOT\fR
+This sets the SLOT for packages that may need to have multiple versions
+co\-exist.  By default you should set \fBSLOT\fR="0".  If you are unsure, then
+do not fiddle with this until you seek some guidance from some guru.  This
+value should \fINEVER\fR be left undefined.
+.TP
+\fBLICENSE\fR
+This should be a space delimited list of licenses that the package falls
+under.  This \fB_must_\fR be set to a matching license in
+/usr/portage/licenses/. If the license does not exist in portage yet, you
+must add it first.
+.TP
+\fBIUSE\fR
+This should be a list of any and all USE flags that are leveraged within
+your build script.  The only USE flags that should not be listed here are
+arch related flags (see \fBKEYWORDS\fR).
+.TP
+\fBDEPEND\fR
+This should contain a list of all packages that are required for the
+program to compile.
+.RS
+.TP
+.B DEPEND Atoms
+A depend atom is simply a dependency that is used by portage when calculating
+relationships between packages.  Please note that if the atom has not already
+been emerged, then the latest version available is matched.
+.RS
+.TP
+.B Atom Bases
+The base atom is just a full category/packagename.  Hence, these are base atoms:
+
+.nf
+.I sys\-apps/sed
+.I sys\-libs/zlib
+.I net\-misc/dhcp
+.fi
+.TP
+.B Atom Versions
+It is nice to be more specific and say that only certain versions of atoms are
+acceptable.  Note that versions must be combined with a prefix (see below).  
+Hence you may add a version number as a postfix to the base:
+
+.nf
+sys\-apps/sed\fI\-4.0.5\fR
+sys\-libs/zlib\fI\-1.1.4\-r1\fR
+net\-misc/dhcp\fI\-3.0_p2\fR
+.fi
+
+Versions are normally made up of two or three numbers separated by periods, such
+as 1.2 or 4.5.2.  This string may be followed by a character such as 1.2a or 
+4.5.2z.  Note that this letter is \fBnot\fR meant to indicate alpha, beta, 
+etc... status.  For that, use the optional suffix; either _alpha, _beta, _pre 
+(pre\-release), _rc (release candidate), or _p (patch).  This means for the 
+3rd pre\-release of a package, you would use something like 1.2_pre3.  The 
+suffixes here can be arbitrarily chained without limitation.
+.TP
+.B Atom Prefix Operators [> >= = <= <]
+Sometimes you want to be able to depend on general versions rather than specifying
+exact versions all the time.  Hence we provide standard boolean operators:
+
+.nf
+\fI>\fRmedia\-libs/libgd\-1.6
+\fI>=\fRmedia\-libs/libgd\-1.6
+\fI=\fRmedia\-libs/libgd\-1.6
+\fI<=\fRmedia\-libs/libgd\-1.6
+\fI<\fRmedia\-libs/libgd\-1.6
+.fi
+.TP
+.B Extended Atom Prefixes [!~] and Postfixes [*]
+Now to get even fancier, we provide the ability to define blocking packages and
+version range matching.  Also note that these extended prefixes/postfixes may
+be combined in any way with the atom classes defined above.  Here are some common
+examples you may find in the portage tree:
+
+.nf
+\fI!\fRapp\-text/dos2unix
+=dev\-libs/glib\-2\fI*\fR
+\fI!\fR=net\-fs/samba\-2\fI*\fR
+\fI~\fRnet\-libs/libnet\-1.0.2a
+.fi
+
+\fI!\fR means block packages from being installed at the same time.
+.br
+\fI*\fR means match any version of the package so long as the specified base
+is matched.  So with a version of '2*', we can match '2.1', '2.2', '2.2.1',
+etc... and not match version '1.0', '3.0', '4.1', etc...
+.br
+\fI~\fR means match any revision of the base version specified.  So in the
+above example, we would match versions '1.0.2a', '1.0.2a\-r1', '1.0.2a\-r2',
+etc...
+.RE
+.TP
+.B Dynamic DEPENDs
+Sometimes programs may depend on different things depending on the USE
+variable.  Portage offers a few options to handle this.  Note that when
+using the following syntaxes, each case is considered as 1 Atom in the
+scope it appears.  That means that each Atom both conditionally include
+multiple Atoms and be nested to an infinite depth.
+.RS
+.TP
+.B usevar? ( DEPEND Atom )
+To include the jpeg library when the user has jpeg in \fBUSE\fR, simply use the
+following syntax:
+.br
+.B jpeg? ( media\-libs/jpeg )
+.TP
+.B !usevar? ( Atom )
+If you want to include a package only if the user does not have a certain option
+in their \fBUSE\fR variable, then use the following syntax:
+.br
+.B !nophysfs? ( dev\-games/physfs )
+.br
+This is often useful for those times when you want to want to add optional support
+for a feature and have it enabled by default.
+.TP
+.B usevar? ( Atom if true ) !usevar? ( Atom if false )
+For functionality like the tertiary operator found in C you must use
+two statements, one normal and one inverted.  If a package uses
+GTK2 or GTK1, but not both, then you can handle that like this:
+.br
+.B gtk2? ( =x11\-libs/gtk+\-2* ) !gtk2? ( =x11\-libs/gtk+\-1* )
+.br
+That way the default is the superior GTK2 library.
+.TP
+.B || ( Atom Atom ... )
+When a package can work with a few different packages but a virtual is not
+appropriate, this syntax can easily be used.
+.nf
+.B || (
+.B 	app\-games/unreal\-tournament
+.B 	app\-games/unreal\-tournament\-goty
+.B )
+.fi
+Here we see that unreal\-tournament has a normal version and it has a goty version.
+Since they provide the same base set of files, another package can use either.
+Adding a virtual is inappropriate due to the small scope of it.
+.br
+Another good example is when a package can be built with multiple video 
+interfaces, but it can only ever have just one.
+.nf
+.B || (
+.B 	sdl? ( media\-libs/libsdl )
+.B 	svga? ( media\-libs/svgalib )
+.B 	opengl? ( virtual/opengl )
+.B 	ggi? ( media\-libs/libggi )
+.B 	virtual/x11
+.B )
+.fi
+Here only one of the packages will be chosen, and the order of preference is
+determined by the order in which they appear.  So sdl has the best chance of being
+chosen, followed by svga, then opengl, then ggi, with a default of X if the user
+does not specify any of the previous choices.
+.RE
+
+.RE
+.TP
+\fBRDEPEND\fR
+This should contain a list of all packages that are required for this
+program to run (aka runtime depend).  If this is not set, then it
+defaults to the value of \fBDEPEND\fR.
+.br
+You may use the same syntax to vary dependencies as seen above in \fBDEPEND\fR.
+.TP
+\fBPDEPEND\fR
+This should contain a list of all packages that will have to be installed after
+the program has been merged.
+.br
+You may use the same syntax to vary dependencies as seen above in \fBDEPEND\fR.
+.TP
+\fBRESTRICT\fR = \fI[strip,mirror,fetch,userpriv]\fR
+This should be a space delimited list of portage features to restrict.
+.PD 0
+.RS
+.TP
+.I binchecks
+Disable all QA checks for binaries.  This should ONLY be used in packages
+for which binary checks make no sense (linux\-headers and kernel\-sources, for
+example, can safely be skipped since they have no binaries).  If the binary
+checks need to be skipped for other reasons (such as proprietary binaries),
+see the \fBQA CONTROL VARIABLES\fR section for more specific exemptions.
+.TP
+.I confcache
+Prevent econf from using confcache.
+.TP
+.I fetch
+like \fImirror\fR but the files will not be fetched via \fBSRC_URI\fR either.
+.TP
+.I mirror
+files in \fBSRC_URI\fR will not be downloaded from the \fBGENTOO_MIRRORS\fR.
+.TP
+.I primaryuri
+fetch from URL's in \fBSRC_URI\fR before \fBGENTOO_MIRRORS\fR.
+.TP
+.I strip
+final binaries/libraries will not be stripped of debug symbols.
+.TP
+.I test
+do not run src_test even if user has \fBFEATURES\fR=test.
+.TP
+.I userpriv
+Disables userpriv for specific packages.
+.RE
+.PD 1
+.TP
+\fBPROVIDE\fR = \fI"virtual/TARGET"\fR
+This variable should only be used when a package provides a virtual target.
+For example, blackdown\-jdk and sun\-jdk provide \fIvirtual/jdk\fR.  This
+allows for packages to depend on \fIvirtual/jdk\fR rather than on blackdown
+or sun specifically.
+.SH "QA CONTROL VARIABLES"
+.TP
+.B USAGE NOTES
+Several QA variables are provided which allow an ebuild to manipulate some
+of the QA checks performed by portage.  Use of these variables in ebuilds
+should be kept to an absolute minimum otherwise they defeat the purpose
+of the QA checks, and their use is subject to agreement of the QA team.
+They are primarily intended for use by ebuilds that install closed\-source
+binary objects that cannot be altered.
+.br
+Note that objects that violate these rules may fail on some architectures.
+.TP
+\fBQA_TEXTRELS\fR
+This variable can be set to a list of file paths, relative to the image
+directory, of files that contain text relocations that cannot be eliminated.
+The paths may contain regular expressions.
+.br
+This variable is intended to be used on closed\-source binary objects that
+cannot be altered.
+.TP
+\fBQA_EXECSTACK\fR
+This should contain a list of file paths, relative to the image directory, of
+objects that require executable stack in order to run.
+The paths may contain regular expressions.
+.br
+This variable is intended to be used on objects that truly need executable
+stack (i.e. not those marked to need it which in fact do not).
+.TP
+\fBQA_WX_LOAD\fR
+This should contain a list of file paths, relative to the image directory, of
+files that contain writable and executable segments.  These are rare.
+The paths may contain regular expressions.
+.SH "PORTAGE DECLARATIONS"
+.TP
+.B inherit
+Inherit is portage's maintenance of extra classes of functions that are
+external to ebuilds and provided as inheritable capabilities and data. They
+define functions and set data types as drop\-in replacements, expanded, and
+simplified routines for extremely common tasks to streamline the build
+process.  Inherit may only be called once in an ebuild and it may \fBnever be
+wrapped within any conditionals\fR of any kind.  Specification of the eclasses
+contains only their name and not the \fI.eclass\fR extension.  Also note that
+the inherit statement must come before other variable declarations.
+.SH "FUNCTIONS"
+.TP
+.B pkg_nofetch
+If you turn on \fIfetch\fR in \fBRESTRICT\fR, then this function will be
+run when the files in \fBSRC_URI\fR cannot be found.  Useful for
+displaying information to the user on *how* to obtain said files.  All
+you have to do is output a message and let the function return.  Do not
+end the function with a call to \fBdie\fR.
+.TP
+.B pkg_setup
+This function can be used if the package needs specific setup actions or
+checks to be preformed before anything else.
+.br
+Initial working directory of ${PORTAGE_TMPDIR}.
+.TP
+.B src_unpack
+This function is used to unpack all the sources in \fIA\fR to \fIWORKDIR\fR.
+If not defined in the \fIebuild script\fR it calls \fIunpack ${A}\fR. Any
+patches and other pre configure/compile modifications should be done here.
+.br
+Initial working directory of $WORKDIR.
+.TP
+.B src_compile
+All necessary steps for configuration and compilation should be done in here.
+.br
+Initial working directory of $S.
+.TP
+.B src_test
+Run all package specific test cases.  The default is to run 'make check'
+followed 'make test'.
+.br
+Initial working directory of $S.
+.TP
+.B src_install
+Should contain everything required to install the package in the temporary
+\fIinstall directory\fR.
+.br
+Initial working directory of $S.
+.TP
+.B pkg_preinst pkg_postinst
+All modifications required on the live\-filesystem before and after the
+package is merged should be placed here. Also commentary for the user
+should be listed here as it will be displayed last.
+.br
+Initial working directory of $PWD.
+.TP
+.B pkg_prerm pkg_postrm
+Like the pkg_*inst functions but for unmerge.
+.br
+Initial working directory of $PWD.
+.TP
+.B pkg_config
+This function should contain optional basic configuration steps.
+.br
+Initial working directory of $PWD.
+.SH "HELPER FUNCTIONS: GENERAL"
+.TP
+\fBdie\fR \fI[reason]\fR
+Causes the current emerge process to be aborted. The final display will
+include \fIreason\fR.
+.TP
+\fBuse\fR \fI<USE item>\fR
+If \fIUSE item\fR is in the \fBUSE\fR variable, the function will silently
+return 0 (aka shell true).  If \fIUSE item\fR is not in the \fBUSE\fR
+variable, the function will silently return 1 (aka shell false).  \fBusev\fR
+is a verbose version of \fBuse\fR.
+.RS
+.TP
+.I Example:
+.nf
+if use gnome ; then
+	guiconf="\-\-enable\-gui=gnome \-\-with\-x"
+elif use gtk ; then
+	guiconf="\-\-enable\-gui=gtk \-\-with\-x"
+elif use X ; then
+	guiconf="\-\-enable\-gui=athena \-\-with\-x"
+else
+	# No gui version will be built
+	guiconf=""
+fi
+.fi
+.RE
+.TP
+\fBuse_with\fR \fI<USE item>\fR \fI[configure name]\fR \fI[configure opt]\fR
+Useful for creating custom options to pass to a configure script. If \fIUSE
+item\fR is in the \fBUSE\fR variable and a \fIconfigure opt\fR is specified,
+then the string \fI\-\-with\-[configure name]=[configure opt]\fR will be echoed.
+If \fIconfigure opt\fR is not specified, then just \fI\-\-with\-[configure
+name]\fR will be echoed.  If \fIUSE item\fR is not in the \fBUSE\fR variable,
+then the string \fI\-\-without\-[configure name]\fR will be echoed. If
+\fIconfigure name\fR is not specified, then \fIUSE item\fR will be used in
+its place.
+.RS
+.TP
+.I Examples:
+.nf
+USE="opengl"
+myconf=$(use_with opengl)
+(myconf now has the value "\-\-with\-opengl")
+
+USE="jpeg"
+myconf=$(use_with jpeg libjpeg)
+(myconf now has the value "\-\-with\-libjpeg")
+
+USE=""
+myconf=$(use_with jpeg libjpeg)
+(myconf now has the value "\-\-without\-libjpeg")
+
+USE="sdl"
+myconf=$(use_with sdl SDL all\-plugins)
+(myconf now has the value "\-\-with\-SDL=all\-plugins")
+.fi
+.RE
+.TP
+\fBuse_enable\fR \fI<USE item>\fR \fI[configure name]\fR \fI[configure opt]\fR
+Same as \fBuse_with\fR above, except that the configure options are
+\fI\-\-enable\-\fR instead of \fI\-\-with\-\fR and \fI\-\-disable\-\fR instead of
+\fI\-\-without\-\fR.
+.TP
+\fBhas\fR \fI<item>\fR \fI<item list>\fR
+If \fIitem\fR is in \fIitem list\fR, then \fIitem\fR is echoed and \fBhas\fR
+returns 0.  Otherwise, nothing is echoed and 1 is returned. As indicated with
+use, there is a non\-echoing version \fBhasq\fR. Please use \fBhasq\fR in all
+places where output is to be disregarded. Never use the output for calculation.
+.br
+The \fIitem list\fR is delimited by the \fIIFS\fR variable.  This variable
+has a default value of ' ', or a space.  It is a \fBbash\fR(1) setting.
+.TP
+\fBhas_version\fR \fI<category/package\-version>\fR
+Check to see if \fIcategory/package\-version\fR is installed on the system.
+The parameter accepts all values that are acceptable in the \fBDEPEND\fR
+variable.  The function returns 0 if \fIcategory/package\-version\fR is
+installed, 1 otherwise.
+.TP
+\fBbest_version\fR \fI<package name>\fR
+This function will look up \fIpackage name\fR in the database of currently
+installed programs and echo the "best version" of the package that is
+currently installed. 
+.RS
+.TP
+.I Example:
+VERINS="$(best_version net\-ftp/glftpd)"
+.br
+(VERINS now has the value "net\-ftp/glftpd\-1.27" if glftpd\-1.27 is installed)
+.RE
+.SH "HELPER FUNCTIONS: OUTPUT"
+.TP
+\fBeinfo\fR \fI"disposable message"\fR
+Same as \fBelog\fR, but should be used when the message isn't important to the
+user (like progress or status messages during the build process).
+.TP
+\fBelog\fR \fI"informative message"\fR
+If you need to display a message that you wish the user to read and take
+notice of, then use \fBelog\fR.  It works just like \fBecho\fR(1), but
+adds a little more to the output so as to catch the user's eye. The message
+will also be logged by portage for later review.
+.TP
+\fBewarn\fR \fI"warning message"\fR
+Same as \fBeinfo\fR, but should be used when showing a warning to the user.
+.TP
+\fBeerror\fR \fI"error message"\fR
+Same as \fBeinfo\fR, but should be used when showing an error to the user.
+.TP
+\fBebegin\fR \fI"helpful message"\fR
+Like \fBeinfo\fR, we output a \fIhelpful message\fR and then hint that the
+following operation may take some time to complete.  Once the task is
+finished, you need to call \fBeend\fR.
+.TP
+\fBeend\fR \fI<status>\fR \fI["error message"]\fR
+Followup the \fBebegin\fR message with an appropriate "OK" or "!!" (for
+errors) marker.  If \fIstatus\fR is non\-zero, then the additional \fIerror
+message\fR is displayed.
+.SH "HELPER FUNCTIONS: UNPACK"
+.TP
+\fBunpack\fR \fI<source>\fR \fI[list of more sources]\fR
+This function uncompresses and/or untars a list of sources into the current
+directory. The function will append \fIsource\fR to the \fBDISTDIR\fR variable.
+.SH "HELPER FUNCTIONS: COMPILE"
+.TP
+\fBeconf\fR \fI[configure options]\fR
+This is used as a replacement for configure.  Performs:
+.nf
+configure \\
+	\-\-prefix=/usr \\
+	\-\-host=${CHOST} \\
+	\-\-mandir=/usr/share/man \\
+	\-\-infodir=/usr/share/info \\
+	\-\-datadir=/usr/share \\
+	\-\-sysconfdir=/etc \\
+	\-\-localstatedir=/var/lib \\
+	\fI${EXTRA_ECONF}\fR \\
+	\fIconfigure options\fR
+.fi
+Note that the \fIEXTRA_ECONF\fR is for users only, not for ebuild
+writers.  If you wish to pass more options to configure, just pass the
+extra arguements to \fBeconf\fR.
+.TP
+\fBemake\fR \fI[make options]\fR
+This is used as a replacement for make.  Performs 'make ${MAKEOPTS}
+\fImake options\fR' (as set in /etc/make.globals), default is MAKEOPTS="\-j2".
+
+\fB***warning***\fR
+.br
+if you are going to use \fBemake\fR, make sure your build is happy with
+parallel makes (make \-j2).  It should be tested thoroughly as parallel
+makes are notorious for failing _sometimes_ but not always.  If you determine
+that your package fails to build in parallel, and you are unable to resolve
+the issue, then you should run '\fBemake\fR \-j1' instead of 'make'.
+.SH "HELPER FUNCTIONS: INSTALL"
+.TP
+\fBeinstall\fR \fI[make options]\fR
+This is used as a replacement for make install.  Performs:
+.nf
+make \\
+	prefix=${D}/usr \\
+	datadir=${D}/usr/share \\
+	infodir=${D}/usr/share/info \\
+	localstatedir=${D}/var/lib \\
+	mandir=${D}/usr/share/man \\
+	sysconfdir=${D}/etc \\
+	\fI${EXTRA_EINSTALL}\fR \\
+	\fImake options\fR \\
+	install
+.fi
+Please do \fBnot\fR use this in place of 'emake install DESTDIR=${D}'.
+That is the preferred way of installing make\-based packages.  Also, do
+not utilize the \fIEXTRA_EINSTALL\fR variable since it is for users.
+
+.PD 0
+.TP
+.B prepall
+.TP
+.B prepalldocs
+.TP
+.B prepallinfo
+.TP
+.B prepallman
+.TP
+.B prepallstrip
+.PD 1
+Useful for when a package installs into \fB${D}\fR via scripts
+(i.e. makefiles).  If you want to be sure that libraries are executable,
+aclocal files are installed into the right place, doc/info/man files are
+all compressed, and that executables are all stripped of debugging symbols,
+then use these suite of functions.
+.RS
+.PD 0
+.TP
+.B prepall:
+Runs \fBprepallman\fR, \fBprepallinfo\fR, \fBprepallstrip\fR, sets
+libraries +x, and then checks aclocal directories.  Please note this
+does \fI*not*\fR run \fBprepalldocs\fR.
+.TP
+.B prepalldocs:
+Compresses all doc files in ${D}/usr/share/doc.
+.TP
+.B prepallinfo:
+Compresses all info files in ${D}/usr/share/info.
+.TP
+.B prepallman:
+Compresses all man files in ${D}/usr/share/man.
+.TP
+.B prepallstrip:
+Strips all executable files of debugging symboles.  This includes libraries.
+.RE
+
+.TP
+\fBprepinfo\fR \fI[dir]\fR
+.TP
+\fBprepman\fR \fI[dir]\fR
+.TP
+\fBprepstrip\fR \fI[dir]\fR
+.PD 1
+Similiar to the \fBprepall\fR functions, these are subtle in their differences.
+.RS
+.PD 0
+.TP
+.B prepinfo:
+If a \fIdir\fR is not specified, then \fBprepinfo\fR will assume the dir
+\fIusr\fR. \fBprepinfo\fR will then compress all the files in
+${D}/\fIdir\fR/info.
+.TP
+.B prepman:
+If a \fIdir\fR is not specified, then \fBprepman\fR will assume the dir
+\fIusr\fR. \fBprepman\fR will then compress all the files in
+${D}/\fIdir\fR/man/*/.
+.TP
+.B prepstrip:
+All the files found in ${D}/\fIdir\fR will be stripped.  You may specify
+multiple directories.
+.RE
+.PD 1
+.TP
+\fBdosed\fR \fI"s:orig:change:g" <filename>\fR
+Performs sed (including cp/mv \fIfilename\fR) on \fIfilename\fR.
+.br
+.BR 'dosed\ "s:/usr/local:/usr:g"\ /usr/bin/some\-script'
+runs sed on ${D}/usr/bin/some\-script
+.TP
+\fBdodir\fR \fI<path>\fR
+Creates a directory inside of ${D}.
+.br
+.BR 'dodir\ /usr/lib/apache'
+creates ${D}/usr/lib/apache.  Note that the do* functions will run
+\fBdodir\fR for you.
+.TP
+\fBdiropts\fR \fI[options for install(1)]\fR
+Can be used to define options for the install function used in
+\fBdodir\fR.  The default is \fI\-m0755\fR.
+.TP
+\fBinto\fR \fI<path>\fR
+Sets the root (\fIDESTTREE\fR) for other functions like \fBdobin\fR,
+\fBdosbin\fR, \fBdoman\fR, \fBdoinfo\fR, \fBdolib\fR.
+.br
+The default root is /usr.
+.TP
+\fBkeepdir\fR \fI<path>\fR
+Tells portage to leave a directory behind even if it is empty.  Functions
+the same as \fBdodir\fR.
+.TP
+\fBdobin\fR \fI<binary> [list of more binaries]\fR
+Installs a \fIbinary\fR or a list of binaries into \fIDESTTREE\fR/bin.
+Creates all necessary dirs.
+.TP
+\fBdosbin\fR \fI<binary> [list of more binaries]\fR
+Installs a \fIbinary\fR or a list of binaries into \fIDESTTREE\fR/sbin.
+Creates all necessary dirs.
+.TP
+\fBdoinitd\fR \fI<init.d script> [list of more init.d scripts]\fR
+Install Gentoo \fIinit.d scripts\fR.  They will be installed into the
+correct location for Gentoo init.d scripts (/etc/init.d/).  Creates all
+necessary dirs.
+.TP
+\fBdoconfd\fR \fI<conf.d file> [list of more conf.d file]\fR
+Install Gentoo \fIconf.d files\fR.  They will be installed into the
+correct location for Gentoo conf.d files (/etc/conf.d/).  Creates all
+necessary dirs.
+.TP
+\fBdoenvd\fR \fI<env.d entry> [list of more env.d entries]\fR
+Install Gentoo \fIenv.d entries\fR.  They will be installed into the
+correct location for Gentoo env.d entries (/etc/env.d/).  Creates all
+necessary dirs.
+
+.PD 0
+.TP
+\fBdolib\fR \fI<library>\fR \fI[list of more libraries]\fR
+.TP
+\fBdolib.a\fR \fI<library>\fR \fI[list of more libraries]\fR
+.TP
+\fBdolib.so\fR \fI<library>\fR \fI[list of more libraries]\fR
+.PD 1
+Installs a library or a list of libraries into \fIDESTTREE\fR/lib.
+Creates all necessary dirs.
+.TP
+\fBlibopts\fR \fI[options for install(1)]\fR
+Can be used to define options for the install function used in
+the \fBdolib\fR functions.  The default is \fI\-m0644\fR.
+.TP
+\fBdoman\fR \fI[\-i18n=<locale>]\fR \fI<man\-page> [list of more man\-pages]\fR
+Installs manual\-pages into /usr/share/man/man[0\-9n] depending on the
+manual file ending.  The files are compressed if they are not already.  You
+can specify locale\-specific manpages with the \fI\-i18n\fR option.  Then the
+man\-page will be installed into /usr/share/man/\fI<locale>\fR/man[0\-9n].
+.PD 0
+.TP
+\fBdohard\fR \fI<filename> <linkname>\fR
+.TP
+\fBdosym\fR \fI<filename> <linkname>\fR
+.PD 1
+Performs the ln command as either a hard link or symlink.
+.TP
+\fBdohtml\fR \fI [\-a filetypes] [\-r] [\-x list\-of\-dirs\-to\-ignore] [list\-of\-files\-and\-dirs]\fR
+Installs the files in the list of files (space\-separated list) into
+/usr/share/doc/${PF}/html provided the file ends in .html, .png, .js, .jpg,
+or .css.  Setting \fI\-a\fR limits what types of files will be included,
+\fI\-A\fR appends to the default list, setting \fI\-x\fR sets which dirs to
+exclude (CVS excluded by default), \fI\-r\fR sets recursive.
+.TP
+\fBdoinfo\fR \fI<info\-file> [list of more info\-files]\fR
+Installs info\-pages into \fIDESTDIR\fR/info.  Files are automatically
+gzipped.  Creates all necessary dirs.
+.TP
+\fBdomo\fR \fI<locale\-file> [list of more locale\-files] \fR
+Installs locale\-files into \fIDESTDIR\fR/usr/share/locale/[LANG]
+depending on local\-file's ending.  Creates all necessary dirs.
+
+.PD 0
+.TP
+\fBfowners\fR \fI<permissions> <file> [files]\fR
+.TP
+\fBfperms\fR \fI<permissions> <file> [files]\fR
+.PD 1
+Performs chown (\fBfowners\fR) or chmod (\fBfperms\fR), applying
+\fIpermissions\fR to \fIfiles\fR.
+.TP
+\fBinsinto\fR \fI[path]\fR
+Sets the destination path for the \fBdoins\fR function.
+.br
+The default path is /.
+.TP
+\fBinsopts\fR \fI[options for install(1)]\fR
+Can be used to define options for the install function used in
+\fBdoins\fR.  The default is \fI\-m0644\fR.
+.TP
+\fBdoins\fR \fI<file> [list of more files]\fR
+Installs files into the path controlled by \fBinsinto\fR.  This function
+uses \fBinstall\fR(1).  Creates all necessary dirs.
+.TP
+\fBexeinto\fR \fI[path]\fR
+Sets the destination path for the \fBdoexe\fR function.
+.br
+The default path is /.
+.TP
+\fBexeopts\fR \fI[options for install(1)]\fR
+Can be used to define options for the install function used in \fBdoexe\fR.
+The default is \fI\-m0755\fR.
+.TP
+\fBdoexe\fR \fI<executable> [list of more executables]\fR
+Installs executables into the path controlled by \fBexecinto\fR.  This function
+uses \fBinstall\fR(1).  Creates all necessary dirs.
+.TP
+\fBdocinto\fR \fI[path]\fR
+Sets the subdir used by \fBdodoc\fR when installing into the document tree
+(based in /usr/share/doc/${PF}/).  Default is no subdir, or just "".
+.TP
+\fBdodoc\fR \fI<document> [list of more documents]\fR
+Installs a document or a list of documents into /usr/share/doc/${PF}/\fI<docinto path>\fR.
+Documents are marked for compression.  Creates all necessary dirs.
+
+.PD 0
+.TP
+\fBnewbin\fR \fI<old file> <new filename>\fR
+.TP
+\fBnewsbin\fR \fI<old file> <new filename>\fR
+.TP
+\fBnewinitd\fR \fI<old file> <new filename>\fR
+.TP
+\fBnewconfd\fR \fI<old file> <new filename>\fR
+.TP
+\fBnewenvd\fR \fI<old file> <new filename>\fR
+.TP
+\fBnewlib\fR \fI<old file> <new filename>\fR
+.TP
+\fBnewlib.so\fR \fI<old file> <new filename>\fR
+.TP
+\fBnewlib.a\fR \fI<old file> <new filename>\fR
+.TP
+\fBnewman\fR \fI<old file> <new filename>\fR
+.TP
+\fBnewinfo\fR \fI<old file> <new filename>\fR
+.TP
+\fBnewins\fR \fI<old file> <new filename>\fR
+.TP
+\fBnewexe\fR \fI<old file> <new filename>\fR
+.TP
+\fBnewdoc\fR \fI<old file> <new filename>\fR
+.PD 1
+All these functions act like the do* functions, but they only work with one
+file and the file is installed as \fI[new filename]\fR.
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "AUTHORS"
+.nf
+Achim Gottinger <achim@gentoo.org>
+Mark Guertin <gerk@gentoo.org>
+Nicholas Jones <carpaski@gentoo.org>
+Mike Frysinger <vapier@gentoo.org>
+Arfrever Frehtes Taifersar Arahesis <FFTA@WP.PL>
+.fi
+.SH "FILES"
+.TP
+The \fI/usr/sbin/ebuild.sh\fR script.
+.TP
+The helper apps in \fI/usr/lib/portage/bin\fR.
+.TP
+\fB/etc/make.conf\fR 
+Contains variables for the build\-process and overwrites those in make.defaults.
+.TP
+\fB/etc/make.globals\fR
+Contains the default variables for the build\-process, you should edit
+\fI/etc/make.conf\fR instead.
+.SH "SEE ALSO"
+.BR ebuild (1),
+.BR make.conf (5)
Index: /vendor/portage/current/man/emaint.1
===================================================================
--- /vendor/portage/current/man/emaint.1	(revision 3419)
+++ /vendor/portage/current/man/emaint.1	(revision 3419)
@@ -0,0 +1,30 @@
+.TH "EMAINT" "1" "Dec 2005" "Portage 2.1" "Portage"
+.SH NAME
+emaint \- updates environment settings automatically
+.SH SYNOPSIS
+.BR emaint
+[\fIoptions\fR]
+[\fBall\fR | \fBworld\fR]
+.SH DESCRIPTION
+.B emaint
+checks for and fixes problems in the portage \fIworld\fR file.
+.SH OPTIONS 
+.TP
+.B \-c, \-\-check
+Check for any problems that may exist.
+.TP
+.B \-f, \-\-fix
+Fix any problems that may exist.
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH AUTHORS
+.nf
+Mike Frysinger <vapier@gentoo.org>
+.fi
+.SH "FILES"
+.TP
+.B /var/lib/portage/world
+Contains a list of all user\-specified packages.
+.SH "SEE ALSO"
+.BR emerge (1),
+.BR portage (5)
Index: /vendor/portage/current/man/emerge.1
===================================================================
--- /vendor/portage/current/man/emerge.1	(revision 3419)
+++ /vendor/portage/current/man/emerge.1	(revision 3419)
@@ -0,0 +1,607 @@
+.TH "EMERGE" "1" "Dec 2006" "Portage 2.1" "Portage"
+.SH "NAME"
+emerge \- Command\-line interface to the Portage system
+.SH "SYNOPSIS"
+.TP
+.BR emerge
+[\fIoptions\fR] [\fIaction\fR] [\fIebuild\fR | \fItbz2file\fR | \fIset\fR | \fIatom\fR] ...
+.TP
+.BR emerge
+\fB\-\-sync\fR | \fB\-\-info\fR | \fB\-\-version\fR
+.TP
+.BR emerge
+\fB\-\-search\fR \fIsomestring\fR
+.TP
+.BR emerge
+\fB\-\-help\fR [\fB\-\-system\fR | \fB\-\-config\fR | \fB\-\-sync\fR]
+.SH "DESCRIPTION"
+\fBemerge\fR is the definitive command\-line interface to the Portage
+system.  It is primarily used for installing packages, and \fBemerge\fR
+can automatically handle any dependencies that the desired package has.
+\fBemerge\fR can also update the \fBportage tree\fR, making new and
+updated packages available.  \fBemerge\fR gracefully handles updating
+installed packages to newer releases as well.  It handles both source
+and binary packages, and it can be used to create binary packages for
+distribution.
+.SH "EBUILDS, TBZ2S, SETS AND ATOMS"
+\fBemerge\fR primarily installs packages.  You can specify
+packages to install in one of four main ways: an \fIebuild\fR,
+a \fItbz2file\fR, a \fIset\fR, or an \fIatom\fR.
+.LP
+.TP
+.BR ebuild
+An \fIebuild\fR must be, at a minimum, a valid Portage
+package directory name without a version or category, such as
+\fBportage\fR or \fBpython\fR.
+Both categories and version numbers may be used in addition, such
+as \fBsys\-apps/portage\fR or \fB=python\-2.2.1\-r2\fR.
+\fBemerge\fR
+ignores a trailing slash so that filename completion can be used.
+The \fIebuild\fR may also be an actual filename, such as
+\fB/usr/portage/app\-admin/python/python\-2.2.1\-r2.ebuild\fR.
+\fBWARNING:\fR The implementation of \fBemerge /path/to/ebuild\fR is broken and
+so this syntax shouldn't be used.
+.TP
+.BR tbz2file
+A \fItbz2file\fR must be a valid .tbz2 created with \fBebuild
+<package>\-<version>.ebuild package\fR or \fBemerge \-\-buildpkg 
+[category/]<package>\fR or \fBquickpkg /var/db/pkg/<category>/<package>\fR.
+.TP
+.BR set
+A \fIset\fR is a convenient shorthand for a large group of
+packages.  Two sets are currently supported: \fBsystem\fR
+and \fBworld\fR.  \fBsystem\fR refers to a set of packages
+deemed necessary for your system to run properly.  \fBworld\fR
+contains all the packages in \fBsystem\fR, plus any
+other packages listed in \fB/var/lib/portage/world\fR.  [See
+\fBFILES\fR below for more information.]  Note that a \fIset\fR
+is generally used in conjunction with \fB\-\-update\fR.
+.TP
+.BR atom
+An \fIatom\fR describes bounds on a package that you wish to install.  
+\fISee portage(5) for the details on atom syntax.\fR  For example, 
+\fB>=dev\-lang/python\-2.2.1\-r2\fR matches the latest available version of 
+Python greater than or equal to 2.2.1\-r2.  Similarly, 
+\fB<dev\-lang/python\-2.0\fR matches the latest available version of Python 
+before 2.0.  Note that in many shells you will need to escape characters such 
+as '<' and '='; use single\- or double\-quotes around the \fIatom\fR 
+to get around escaping problems.
+.SH "ACTIONS"
+.TP
+.BR "No action"
+If no action is specified, the action is to merge in the specified
+packages, satisfying any dependencies that they may have.  The
+arguments can be \fIebuilds\fR, \fItbz2s\fR, \fIsets\fR, or
+\fIatoms\fR.  \fBNote that you need to use the \-\-usepkg 
+option if you want to install a tbz2\fR.  The packages are added
+to the \fBworld\fR file at the end, so that they are considered for
+later updating.
+.TP
+.BR "\-\-clean " (\fB\-c\fR)
+Cleans up the system by examining the installed packages and removing older
+packages.  This is accomplished by looking at each installed package and separating
+the installed versions by \fBslot\fR.  Clean will \fBremove all but the most recently
+installed version in each \fbslot\fR.  Clean should not remove unslotted packages.
+Note: Most recently installed means most \fBrecent\fR, not highest version.
+.TP
+.BR "\-\-config "
+Run package specific actions needed to be executed after the emerge process 
+has completed.  This usually entails configuration file setup or other similar 
+setups that the user may wish to run.
+.TP
+.BR \-\-depclean
+Determines all packages installed on the system that have no 
+explicit reason for being there.  \fBemerge\fR generates a list 
+of packages which it expects to be installed by checking the 
+\fBsystem\fR package list and the \fBworld\fR file.  It then 
+compares that list to the list of packages which are actually 
+installed; the differences are listed as unnecessary packages 
+and then unmerged after a short timeout.  \fBWARNING: Removing some 
+packages may cause packages which link to the removed package 
+to stop working and complain about missing libraries.\fR 
+Re\-emerge the complaining package to fix this issue.  Also see
+\fB\-\-with\-bdeps\fR for behavior with respect to build time dependencies that
+are not strictly required.
+.TP
+.BR "\-\-help " (\fB\-h\fR)
+Displays help information for emerge.  Adding one of the additional
+arguments listed above will give you more specific help information
+on that subject.  The internal \fBemerge\fR help documentation is
+updated more frequently than this man page; check it out if you
+are having problems that this man page does not help resolve.
+.TP
+.BR \-\-info
+Produces a list of information to include in bug reports which aids the 
+developers when fixing the reported problem.  \fBPlease include this 
+information when submitting a bug report.\fR  Expanded output can be obtained 
+with the \fI\-\-verbose\fR option.
+.TP
+.BR \-\-metadata
+Transfers metadata cache from ${PORTDIR}/metadata/cache/ to
+/var/cache/edb/dep/ as is normally done on the
+tail end of an rsync update using \fBemerge \-\-sync\fR.  This process
+populates the cache database that portage uses for pre-parsed lookups of
+package data.  It does not populate cache for the overlays listed in
+PORTDIR_OVERLAY.  In order to generate cache for overlays, use \fB\-\-regen\fR.
+.TP
+.BR "\-\-prune " (\fB\-P\fR)
+\fBWARNING: This action can remove important packages!\fR  Prune looks at each
+installed package and attempts to \fBremove\fR all but the \fBmost recently 
+installed version.  \fRPrune ignores \fBslots\fR, if you require a slot\-aware
+Prune use \fB emerge \-\-clean\fR.  Prune may inadvertently remove important 
+packages from your system.  Use \fB\-\-clean\fR instead unless you really 
+know what you're doing.
+.TP
+.BR \-\-regen
+Causes portage to check and update the dependency cache of all ebuilds in the 
+portage tree.  The cache is used to speed up searches and the building of 
+dependency trees.  This command is not recommended for rsync users as rsync 
+updates the cache using server\-side caches.  If you do not know the 
+differences between a 'rsync user' and some other user, then you are a 'rsync 
+user' :).  Rsync users should simply run \fBemerge \-\-sync\fR to regenerate 
+the cache.  After a portage update, rsync users may find it convenient to run 
+\fBemerge \-\-metadata\fR to rebuild the cache as portage does at the end of 
+a sync operation.
+.TP
+.BR "\-\-resume"
+Resumes the last merge operation.  Please note that this operation
+will only return an error on failure.  If there is nothing for portage
+to do, then portage will exit with a message and a success condition.
+.TP
+.BR "\-\-search " (\fB\-s\fR)
+Searches for matches of the supplied string in the portage tree.
+By default emerge uses a case-insensitive simple search, but you can 
+enable a regular expression search by prefixing the search string with %.
+For example, \fBemerge \-\-search "%^kde"\fR searches for any package whose 
+name starts with "kde"; \fBemerge \-\-search "%gcc$"\fR searches for any 
+package that ends with "gcc"; \fBemerge \-\-search "office"\fR searches for 
+any package that contains the word "office".  If you want to include the 
+category into the search string, prepend an @: \fBemerge --search 
+"%@^dev-java.*jdk"\fR. If you want to search the package descriptions as well, 
+use the \fB\-\-searchdesc\fR action.
+.TP
+.BR "\-\-searchdesc " (\fB\-S\fR)
+Matches the search string against the description field as well as
+the package name.  \fBTake caution\fR as the descriptions are also
+matched as regular expressions.
+.TP
+.BR \-\-sync
+Initiates a portage tree update with one of the rsync.gentoo.org
+mirrors.  \fBNote that any changes you have made to the portage
+tree will be erased\fR.  Except for special circumstances, 
+this uses \fBrsync\fR to do the update.  See \fBmake.conf\fR(5)'s 
+description of PORTDIR_OVERLAY for a method to avoid deletions.
+.TP
+.BR "\-\-unmerge " (\fB\-C\fR)
+\fBWARNING: This action can remove important packages!\fR Removes
+all matching packages.  This does no checking of dependencies, so
+it may remove packages necessary for the proper operation of your
+system.  Its arguments can be \fIebuilds\fR, \fIsets\fR, or
+\fIatoms\fR.
+.TP
+.BR "\-\-update " (\fB\-u\fR)
+Updates packages to the best version available, which may not always be the 
+highest version number due to masking for testing and development.  This will 
+also update direct dependencies which may not be what you want.  Package atoms
+specified on the command line are greedy, meaning that unspecific atoms may
+match multiple installed versions of slotted packages.
+.TP
+.BR "\-\-version " (\fB\-V\fR)
+Displays the version number of \fBemerge\fR.
+.SH "OPTIONS"
+.TP
+.BR "\-\-alphabetical "
+When displaying USE and other flag output, combines the enabled and
+disabled lists into one list and sorts the whole list alphabetically.
+.TP
+.BR "\-\-ask " (\fB\-a\fR)
+Before performing the action, display what will take place (server info for
+\fB\-\-sync\fR, \fB\-\-pretend\fR output for merge, and so forth), then ask
+whether to proceed with the action or abort.  Using \fB\-\-ask\fR is more
+efficient than using \fB\-\-pretend\fR and then executing the same command
+without \fB\-\-pretend\fR, as dependencies will only need to be calculated once.
+\fBWARNING: If the "Enter" key is pressed at the prompt (with no other input),
+it is interpreted as acceptance of the first choice.  Note that the input
+buffer is not cleared prior to the prompt, so an accidental press of the
+"Enter" key at any time prior to the prompt will be interpreted as a choice!\fR
+.TP
+.BR "\-\-buildpkg " (\fB\-b\fR)
+Tells emerge to build binary packages for all ebuilds processed in
+addition to actually merging the packages.  Useful for maintainers
+or if you administrate multiple Gentoo Linux systems (build once,
+emerge tbz2s everywhere).  The package will be created in the
+\fI${PKGDIR}/All\fR directory.  An alternative for already\-merged
+packages is to use \fBquickpkg\fR which creates a tbz2 from the
+live filesystem.
+.TP
+.BR "\-\-buildpkgonly " (\fB\-B\fR)
+Creates binary packages for all ebuilds processed without actually
+merging the packages.  This comes with the caveat that all build-time 
+dependencies must already be emerged on the system.
+.TP
+.BR "\-\-changelog " (\fB\-l\fR)
+Use this in conjunction with the \fB\-\-pretend\fR option.  This will
+show the ChangeLog entries for all the packages that will be upgraded.
+.TP
+.BR "\-\-color < y | n >"
+Enable or disable color output.  This option will override \fINOCOLOR\fR
+(see \fBmake.conf\fR(5)) and may also be used to force color output when stdout
+is not a tty (by default, color is disabled unless stdout is a tty).
+.TP
+.BR "\-\-columns"
+Used alongside \fB\-\-pretend\fR to cause the package name, new version, 
+and old version to be displayed in an aligned format for easy cut\-n\-paste.
+.TP
+.BR \-\-config\-root=DIR
+Set the \fBPORTAGE_CONFIGROOT\fR environment variable.
+.TP
+.BR "\-\-debug " (\fB\-d\fR)
+Tells emerge to run the emerge command in \fB\-\-debug\fR mode.  In this
+mode the bash build environment will run with the \-x option, causing 
+it to output verbose debugging information to stdout.  This also enables
+a plethora of other output (mostly dependency resolution messages).
+.TP
+.BR "\-\-deep " (\fB\-D\fR)
+This flag forces
+\fBemerge\fR to consider the entire dependency tree of packages,
+instead of checking only the immediate dependencies of the packages.
+As an example, this catches updates in libraries that are not directly
+listed in the dependencies of a package.  Also see \fB\-\-with\-bdeps\fR for
+behavior with respect to build time dependencies that are not strictly
+required.
+.TP
+.BR "\-\-emptytree " (\fB\-e\fR)
+Reinstalls all world packages and their dependencies to the current USE 
+specifications while differing from the installed set of packages as 
+little as possible.  You should run with \fB\-\-pretend\fR first to make 
+sure the result is what you expect.
+.TP
+.BR "\-\-fetchonly " (\fB\-f\fR)
+Instead of doing any package building, just perform fetches for all
+packages (the main package as well as all dependencies).
+.TP
+.BR "\-\-fetch\-all\-uri " (\fB\-F\fR)
+Instead of doing any package building, just perform fetches for all
+packages (the main package as well as all dependencies), grabbing all potential
+files.
+.TP
+.BR "\-\-getbinpkg " (\fB\-g\fR)
+Using the server and location defined in \fIPORTAGE_BINHOST\fR (see 
+\fBmake.conf\fR(5)), portage will download the information from each binary 
+package found and it will use that information to help build the dependency 
+list.  This option implies \fB\-k\fR.  (Use \fB\-gK\fR for binary\-only 
+merging.)
+.TP
+.BR "\-\-getbinpkgonly " (\fB\-G\fR)
+This option is identical to \fB\-g\fR, as above, except it will not use ANY 
+information from the local machine.  All binaries will be downloaded from the 
+remote server without consulting packages existing in the local packages 
+directory.
+.TP
+.BR "\-\-ignore-default-opts"
+Causes \fIEMERGE_DEFAULT_OPTS\fR (see \fBmake.conf\fR(5)) to be ignored.
+.TP
+.BR "\-\-newuse " (\fB\-N\fR)
+Tells emerge to include installed packages where USE flags have changed since 
+compilation.  USE flag changes include:
+
+A USE flag was added to a package.
+A USE flag was removed from a package.
+A USE flag was turned on for a package.
+A USE flag was turned off for a package.
+
+USE flags may be toggled by your profile as well as your USE and package.use
+settings.
+.TP
+.BR "\-\-noconfmem"
+Causes portage to disregard merge records indicating that a config file
+inside of a \fBCONFIG_PROTECT\fR directory has been merged already.  Portage
+will normally merge those files only once to prevent the user from
+dealing with the same config multiple times.  This flag will cause the
+file to always be merged.
+.TP
+.BR "\-\-nodeps " (\fB\-O\fR)
+Merges specified packages without merging any dependencies.  Note that
+the build may fail if the dependencies aren't satisfied.
+.TP
+.BR "\-\-noreplace " (\fB\-n\fR)
+Skips the packages specified on the command\-line that have already
+been installed.  Without this option, any packages, ebuilds, or deps
+you specify on the command\-line \fBwill\fR cause Portage to remerge
+the package, even if it is already installed.  Note that Portage will
+not remerge dependencies by default.
+.TP
+.BR "\-\-nospinner"
+Disables the spinner for the session.  The spinner is active when the
+terminal device is determined to be a TTY.  This flag disables it regardless.
+.TP
+.BR "\-\-oneshot " (\fB\-1\fR)
+Emerge as normal, but do not add the packages to the world file
+for later updating.
+.TP
+.BR "\-\-onlydeps " (\fB\-o\fR)
+Only merge (or pretend to merge) the dependencies of the packages
+specified, not the packages themselves.
+.TP
+.BR "\-\-pretend " (\fB\-p\fR)
+Instead of actually performing the merge, simply display what *would*
+have been installed if \fB\-\-pretend\fR weren't used.  Using \fB\-\-pretend\fR
+is strongly recommended before installing an unfamiliar package.  In
+the printout:
+.br 
+ 
+.br 
+\fIN\fR = new (not yet installed)
+.br 
+\fIS\fR = new SLOT installation (side-by-side versions) 
+.br 
+\fIU\fR = updating (to another version)
+.br 
+\fID\fR = downgrading (best version seems lower)
+.br 
+\fIR\fR = replacing (remerging same version))
+.br 
+\fIF\fR = fetch restricted (must be manually downloaded)
+.br 
+\fIf\fR = fetch restricted (already downloaded)
+.br 
+\fIB\fR = blocked by an already installed package
+.TP
+.BR "\-\-quiet " (\fB\-q\fR)
+Results may vary, but the general outcome is a reduced or condensed
+output from portage's displays.
+.TP
+.BR "\-\-skipfirst"
+This option is only valid when used with \fB\-\-resume\fR.  It removes the 
+first package in the resume list so that a merge may continue in the presence 
+of an uncorrectable or inconsequential error.  This should only be used in 
+cases where skipping the package will not result in failed dependencies.
+.TP
+.BR "\-\-tree " (\fB\-t\fR)
+Shows the dependency tree for the given target by indenting dependencies.
+This is only really useful in combination with \fB\-\-emptytree\fR or 
+\fB\-\-update\fR and \fB\-\-deep\fR.
+.TP
+.BR "\-\-usepkg " (\fB\-k\fR) 
+Tells emerge to use binary packages (from $PKGDIR) if they are available, thus 
+possibly avoiding some time\-consuming compiles.  This option is useful for CD 
+installs; you can export PKGDIR=/mnt/cdrom/packages and then use this option to 
+have emerge "pull" binary packages from the CD in order to satisfy dependencies.
+.TP
+.BR "\-\-usepkgonly " (\fB\-K\fR)
+Tells emerge to only use binary packages (from $PKGDIR).  All the binary 
+packages must be available at the time of dependency calculation or emerge 
+will simply abort.  Portage does not use $PORTDIR when calculating dependency 
+information so all masking information is ignored.
+.TP
+.BR "\-\-verbose " (\fB\-v\fR)
+Tell emerge to run in verbose mode.  Currently this flag causes emerge to print 
+out GNU info errors, if any, and to show the USE flags that will be used for 
+each package when pretending. The following symbols are affixed to USE flags
+in order to indicate their status:
+.br
+
+.br
+\fI- prefix\fR     = not enabled (either disabled or removed)
+.br
+\fI* suffix\fR     = transition to or from the enabled state
+.br
+\fI% suffix\fR     = newly added or removed
+.br
+\fI() circumfix\fR = forced, masked, or removed
+.TP
+.BR "\-\-with\-bdeps < y | n >"
+In dependency calculations, pull in build time dependencies that are not
+strictly required.   This defaults to \'n\' for installation actions and
+\'y\' for the \fB\-\-depclean\fR action.  This setting can be added to
+\fBEMERGE_DEFAULT_OPTS\fR (see make.conf(5)) and later overridden via the
+command line.
+.SH "ENVIRONMENT OPTIONS"
+.TP
+\fBROOT\fR = \fI[path]\fR
+Use \fBROOT\fR to specify the target root filesystem to be used for
+merging packages or ebuilds.  This variable can be set in \fBmake.conf\fR(5)
+when \fBPORTAGE_CONFIGROOT\fR has a value other than /.
+.br
+Defaults to /.
+.TP
+\fBPORTAGE_CONFIGROOT\fR = \fI[path]\fR
+Use \fBPORTAGE_CONFIGROOT\fR to specify the location for various portage 
+configuration files
+(see \fBFILES\fR for a detailed list of configuration files).  This variable
+can be set via the \fB\-\-config\-root\fR option.
+.br
+Defaults to /.
+.SH "OUTPUT"
+When utilizing \fBemerge\fR with the \fB\-\-pretend\fR and \fB\-\-verbose\fR 
+flags, the output may be a little hard to understand at first.  This section
+explains the abbreviations.
+.TP
+.B [blocks B     ] app\-text/dos2unix (from pkg app\-text/hd2u\-0.8.0)
+Dos2unix is Blocking hd2u from being emerged.  Blockers are defined when
+two packages will clobber each others files, or otherwise cause some form
+of breakage in your system.  However, blockers usually do not need to be
+simultaneously emerged because they usually provide the same functionality.
+.TP
+.B [ebuild  N    ] app\-games/qstat\-25c
+Qstat is New to your system, and will be emerged for the first time.
+.TP
+.B [ebuild  NS   ] dev-libs/glib-2.4.7
+You already have a version of glib installed, but a 'new' version in 
+a different SLOT is available.
+.TP
+.B [ebuild   R   ] sys\-apps/sed\-4.0.5
+Sed 4.0.5 has already been emerged, but if you run the command, then 
+portage will Re\-emerge the specified package (sed in this case).
+.TP
+.B [ebuild    F  ] media\-video/realplayer\-8\-r6
+The realplayer package requires that you Fetch the sources manually.  
+When you attempt to emerge the package, if the sources are not found, 
+then portage will halt and you will be provided with instructions on how 
+to download the required files.
+.TP
+.B [ebuild    f  ] media\-video/realplayer\-8\-r6
+The realplayer package's files are already downloaded.
+.TP
+.B [ebuild     U ] net\-fs/samba\-2.2.8_pre1 [2.2.7a]
+Samba 2.2.7a has already been emerged and can be Updated to version 
+2.2.8_pre1.
+.TP
+.B [ebuild     UD] media\-libs/libgd\-1.8.4 [2.0.11]
+Libgd 2.0.11 is already emerged, but if you run the command, then 
+portage will Downgrade to version 1.8.4 for you.
+.br 
+This may occur if a newer version of a package has been masked because it is
+broken or it creates a security risk on your system and a fix has not been
+released yet.
+.br 
+Another reason this may occur is if a package you are trying to emerge requires
+an older version of a package in order to emerge successfully.  In this case,
+libgd 2.x is incompatible with libgd 1.x.  This means that packages that were
+created with libgd 1.x will not compile with 2.x and must downgrade libgd first
+before they can emerge.
+.TP
+.B [ebuild     U ] sys\-devel/distcc\-2.16 [2.13\-r1] USE="ipv6* \-gtk \-qt%"
+Here we see that the make.conf variable \fBUSE\fR affects how this package is
+built.  In this example, ipv6 optional support is enabled and both gtk and qt
+support are disabled.  The asterisk following ipv6 indicates that ipv6 support
+was disabled the last time this packages was installed.  The percent sign
+following qt indicates that the qt option has been added to the package since
+it was last installed.
+.br
+\fB*Note:\fR Flags that haven't changed since the last install are only
+displayed when you use the \fB\-\-pretend\fR and \fB\-\-verbose\fR options.
+Using the \fB\-\-quiet\fR option will prevent all information from being
+displayed.
+.SH "NOTES"
+You should almost always precede any package install or update attempt with a 
+\fB\-\-pretend\fR install or update.  This lets you see how much will be 
+done, and shows you any blocking packages that you will have to rectify.  
+This goes doubly so for the \fBsystem\fR and \fBworld\fR sets, which can 
+update a large number of packages if the portage tree has been particularly 
+active.
+.LP
+You also want to typically use \fB\-\-update\fR, which ignores packages that 
+are already fully updated but updates those that are not.
+.LP
+When you install a package with uninstalled dependencies and do
+not explicitly state those dependencies in the list of parameters,
+they will not be added to the world file.  If you want them to be
+detected for world updates, make sure to explicitly list them as
+parameters to \fBemerge\fR.
+.LP
+\fBUSE variables\fR may be specified on the command line to
+override those specified in the default locations, letting you
+avoid using some dependencies you may not want to have.  \fBUSE
+flags specified on the command line are NOT remembered\fR.  For
+example, \fBenv USE="\-X \-gnome" emerge mc\fR will emerge mc with
+those USE settings (on Bourne-compatible shells you may omit the \fBenv\fR
+part).  If you want those USE settings to be more 
+permanent, you can put them in /etc/portage/package.use instead.
+.LP
+If \fBemerge \-\-update system\fR or \fBemerge \-\-update world\fR
+fails with an error message, it may be that an ebuild uses some
+newer feature not present in this version of \fBemerge\fR.  You
+can use \fBemerge \-\-update portage\fR to upgrade to the lastest
+version, which should support any necessary new features.
+.SH "MASKED PACKAGES"
+\fINOTE: Please use caution when using development packages.  Problems
+and bugs resulting from misusing masked packages drains Gentoo
+developer time.  Please be sure you are capable of handling any problems
+that may ensue.\fR
+.LP
+Masks in \fBportage\fR provide three primary functions: they allow a
+testing period where the packages can be used in live machines; they
+prevent the use of a package when it will fail; and they mask existing
+packages that are broken or could pose a security risk.  Masking can be
+done by two methods: \fBpackage.mask\fR and \fBKEYWORDS\fR.  Read below
+to find out how to unmask in either case.  Also note that if you give 
+\fBemerge\fR an ebuild, then all forms of masking will be ignored and
+\fBemerge\fR will attempt to emerge the package.
+.TP
+.BR package.mask
+The \fBpackage.mask\fR file primarily blocks the use of packages that cause
+problems or are known to have issues on different systems.  It resides in
+\fI/usr/portage/profiles\fR.
+.TP
+.BR KEYWORDS
+The \fBKEYWORDS\fR variable in an \fBebuild\fR file is also used for masking 
+a package still in testing.  There are architecture\-specific keywords for 
+each package that let \fBportage\fR know which systems are compatible with 
+the package.  Packages which compile on an architecture, but have not been 
+proven to be "stable", are masked with a tilde (\fB~\fR) in front of the 
+architecture name.  \fBemerge\fR examines the \fBACCEPT_KEYWORDS\fR environment 
+variable to allow or disallow the emerging of a package masked by 
+\fBKEYWORDS\fR.  To inform \fBemerge\fR that it should build these 'testing' 
+versions of packages, you should update your 
+\fI/etc/portage/package.keywords\fR file to list the packages you want the 
+\'testing\' version.  See \fBportage\fR(5) for more information.
+.SH "REPORTING BUGS"
+Please report any bugs you encounter through our website:
+.LP
+\fBhttp://bugs.gentoo.org/\fR
+.LP
+Please include the output of \fBemerge \-\-info\fR when you submit your
+bug report.
+.SH "AUTHORS"
+.nf
+Daniel Robbins <drobbins@gentoo.org>
+Geert Bevin <gbevin@gentoo.org>
+Achim Gottinger <achim@gentoo.org>
+Nicholas Jones <carpaski@gentoo.org>
+Phil Bordelon <phil@thenexusproject.org>
+Mike Frysinger <vapier@gentoo.org>
+Marius Mauch <genone@gentoo.org>
+.fi
+.SH "FILES"
+Here is a common list of files you will probably be interested in.  For a 
+complete listing, please refer to the \fBportage\fR(5) man page.
+.TP
+.B /var/lib/portage/world
+Contains a list of all user\-specified packages.  You can safely edit
+this file, adding packages that you want to be considered in \fBworld\fR
+set updates and removing those that you do not want to be considered.
+.TP
+.B /etc/make.conf
+Contains variables for the build process, overriding those in
+\fBmake.globals\fR.  \fBYou should edit this file instead of the ones
+listed below\fR.
+.TP
+.B /etc/dispatch\-conf.conf
+Contains settings to handle automatic updates/backups of configuration 
+files.
+.TP
+.B /etc/make.profile/make.defaults
+Contains profile\-specific variables for the build process.  \fBDo not
+edit this file\fR.
+.TP
+.B /etc/make.profile/use.defaults
+Contains a list of packages which, if installed, cause the respective USE 
+flag to be enabled by default.  \fBDo not edit this file\fR.
+.TP
+.B /usr/portage/profiles/use.desc
+Contains the master list of USE flags with descriptions of their
+functions.  \fBDo not edit this file\fR.
+.TP
+.B /etc/make.profile/virtuals
+Contains a list of default packages used to resolve virtual dependencies.
+\fBDo not edit this file\fR.
+.TP
+.B /etc/make.profile/packages
+Contains a list of packages used for the base system.  The \fBsystem\fR
+and \fBworld\fR sets consult this file.  \fBDo not edit this file\fR.
+.TP
+.B /etc/make.globals
+Contains the default variables for the build process.  \fBDo not edit
+this file\fR.
+.SH "SEE ALSO"
+.BR "emerge \-\-help",
+.BR ebuild (1),
+.BR ebuild (5),
+.BR make.conf (5),
+.BR portage (5)
+.LP
+A number of helper applications reside in \fI/usr/lib/portage/bin\fR.
+.LP
+The \fBapp\-portage/gentoolkit\fR package contains useful scripts such as 
+\fBequery\fR (a package query tool).
Index: /vendor/portage/current/man/env-update.1
===================================================================
--- /vendor/portage/current/man/env-update.1	(revision 3419)
+++ /vendor/portage/current/man/env-update.1	(revision 3419)
@@ -0,0 +1,28 @@
+.TH "ENV-UPDATE" "1" "Mar 2006" "Portage 2.1" "Portage"
+.SH NAME
+env\-update \- updates environment settings automatically
+.SH SYNOPSIS
+\fBenv\-update\fR \fI[options]\fR
+.SH DESCRIPTION
+.B env\-update
+reads the files in \fI/etc/env.d\fR and automatically generates
+\fI/etc/profile.env\fR and \fI/etc/ld.so.conf\fR.  Then \fBldconfig\fR(8)
+is run to update \fI/etc/ld.so.cache\fR.  \fBenv-update\fR is run by
+\fBemerge\fR(1) automatically after each package merge.  Also, if you
+make changes to \fI/etc/env.d\fR, you should run \fIenv-update\fR 
+yourself for changes to take effect immediately.  Note that this would 
+only affect new processes.  In order for the changes to affect your 
+active shell, you will probably have to run \fIsource /etc/profile\fR 
+first.
+.SH OPTIONS 
+.TP
+.B \-\-no\-ldconfig
+Do not run ldconfig (and thus skip rebuilding the ldso cache, updating the 
+links in library paths, etc...).
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH AUTHORS
+Daniel Robbins <drobbins@gentoo.org>
+.SH "SEE ALSO"
+.BR emerge (1),
+.BR ldconfig (8)
Index: /vendor/portage/current/man/etc-update.1
===================================================================
--- /vendor/portage/current/man/etc-update.1	(revision 3419)
+++ /vendor/portage/current/man/etc-update.1	(revision 3419)
@@ -0,0 +1,38 @@
+.TH "ETC-UPDATE" "1" "Dec 2005" "Portage 2.1" "Portage"
+.SH NAME
+etc-update \- handle configuration file updates
+.SH SYNOPSIS
+.B etc-update
+.SH DESCRIPTION
+.I etc-update
+is supposed to be run after merging a new package to see if
+there are updates to the configuration files.  If a new
+configuration file will override an old one, 
+.I etc-update 
+will prompt the user for a decision.
+.PP
+.I etc-update
+will check all directories in the \fICONFIG_PROTECT\fR variable.  All
+config files found in \fICONFIG_PROTECT_MASK\fR will automatically be
+updated for you by \fIetc-update\fR.  See \fBmake.conf\fR(5) for more
+information.
+.SH OPTIONS
+.TP
+None.
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH AUTHORS
+.nf
+Jochem Kossen and Leo Lipelis
+Karl Trygve Kalleberg <karltk@gentoo.org>
+Mike Frysinger <vapier@gentoo.org>
+.fi
+.SH "FILES"
+.TP
+.B /etc/etc-update.conf
+Configuration settings for \fIetc-update\fR are stored here.
+.TP
+.B /etc/dispatch-conf.conf
+Settings for dispatching configuration files right before they're merged.
+.SH "SEE ALSO"
+.BR make.conf (5)
Index: /vendor/portage/current/man/make.conf.5
===================================================================
--- /vendor/portage/current/man/make.conf.5	(revision 3419)
+++ /vendor/portage/current/man/make.conf.5	(revision 3419)
@@ -0,0 +1,509 @@
+.TH "MAKE.CONF" "5" "Jan 2007" "Portage 2.1.2" "Portage"
+.SH "NAME"
+make.conf \- custom settings for Portage
+.SH "SYNOPSIS"
+.B /etc/make.conf
+.SH "DESCRIPTION"
+This file contains various variables that are used by Portage.
+Portage will check the currently\-defined environment variables
+first for any settings.  If no environment settings are found,
+Portage then checks /etc/make.conf.  If no setting is found
+in /etc/make.conf, Portage checks /etc/make.globals. If no
+setting is found there, the profile's default setting is grabbed
+from /etc/make.profile/make.defaults. Please note that all user
+settings should be made in the environment or in /etc/make.conf,
+which is intended to be customized by the user.
+.br
+Exceptions are incremental variables such as USE, CONFIG_PROTECT*,
+and ACCEPT_KEYWORDS.  Incremental variables are propagated down from
+make.defaults to make.globals to make.conf to the environment
+settings.  Clearing these variables requires a clear\-all as in:
+export USE="\-*"
+.SH "VARIABLES"
+.TP
+\fBACCEPT_KEYWORDS\fR = \fI[space delimited list of KEYWORDS]\fR
+Enable testing of ebuilds that have not yet been deemed 'stable'.  Users
+of the 'x86' architecture would set this to '~x86' while ppc users would
+set this to '~ppc'.  This is an incremental variable.  Only define a 
+~arch.
+.br
+Defaults to the value of $ARCH.
+.TP
+\fBBUILD_PREFIX\fR = \fI[path]\fR
+Defines the location of the package working directory. 
+.br
+Defaults to ${PORTAGE_TMPDIR}/portage
+.TP
+.B CBUILD
+This variable is passed by the \fIebuild scripts\fR to the \fIconfigure\fR
+as \fI\-\-build=${CBUILD}\fR only if it is defined.  Do not set this yourself
+unless you know what you are doing.
+.TP
+\fBCCACHE_DIR\fR = \fI[path]\fR
+Defines the location of the ccache working directory.  See the \fBccache\fR(1)
+man page for more information.
+.br
+Defaults to /var/tmp/ccache
+.TP
+\fBCCACHE_SIZE\fR = \fI"size"\fR
+This controls the space use limitations for ccache.  The default is 2 gigabytes 
+('2G').  Sizes are specified with 'G', 'M', or 'K'.
+.TP
+.B CFLAGS CXXFLAGS
+Use these variables to set the desired optimization/CPU instruction settings
+for applications that you compile.  Nearly all ebuild files will take advantage
+of your custom settings, resulting in a Gentoo Linux that is fully customized
+to your specifications.  Please use sane settings as some packages will fail to
+compile/run if the optimizations are too extreme.
+
+For more information, see the \fIInvoking GCC\fR section of the gcc manual:
+.br
+http://gcc.gnu.org/onlinedocs/
+.TP
+.B CHOST
+This variable is passed by the \fIebuild scripts\fR to the \fIconfigure\fR
+step as \fI\-\-host=${CHOST}\fR.  This way you can force the build\-host.
+
+For more information:
+.br
+http://gcc.gnu.org/onlinedocs/gcc\-4.1.1/gcc/Submodel\-Options.html
+.br
+http://gcc.gnu.org/onlinedocs/gcc\-3.3/gcc/Submodel\-Options.html
+.br
+http://gcc.gnu.org/onlinedocs/gcc\-3.2/gcc/Submodel\-Options.html
+.br
+http://gcc.gnu.org/onlinedocs/gcc\-2.95.3/gcc_2.html
+.TP
+\fBCLEAN_DELAY\fR = \fIinteger\fR
+Determines how long the countdown delay will be after running `emerge clean`.
+.br
+Defaults to 5 seconds.
+.TP
+\fBCOLLISION_IGNORE\fR = \fI[space delimited list of files and/or directories]\fR
+This variable allows the user to disable \fIcollision\-protect\fR for specific
+files and/or directories.
+.TP
+\fBCONFIG_PROTECT\fR = \fI[space delimited list of files and/or directories]\fR
+All files and/or directories that are defined here will have "config file protection"
+enabled for them.  For more information, please see `emerge \-\-help config`.
+.TP
+\fBCONFIG_PROTECT_MASK\fR = \fI[space delimited list of files and/or directories]\fR
+All files and/or directories that are defined here will have "config file protection"
+disabled for them.  For more information, please see `emerge \-\-help config`.
+.TP
+.B CTARGET
+This variable is passed by the \fIebuild scripts\fR to the \fIconfigure\fR
+as \fI\-\-target=${CTARGET}\fR only if it is defined.
+.TP
+\fBDISTDIR\fR = \fI[path]\fR
+Defines the location of your local source file repository.
+.br
+Defaults to ${PORTDIR}/distfiles.
+.TP
+.B DOC_SYMLINKS_DIR
+If this variable contains a directory then symlinks to html documentation will
+be installed into it.
+.TP
+.B EBEEP_IGNORE
+Defines whether or not to ignore audible beeps when displaying important
+informational messages.  This variable is unset by default.
+.TP
+.B EMERGE_DEFAULT_OPTS
+Options to append to the end of the \fBemerge\fR(1) command line on every invocation.
+These options will not be appended to the command line if \-\-ignore\-default\-opts
+is specified.
+.TP
+.B EPAUSE_IGNORE
+Defines whether or not to ignore short pauses that occur when displaying
+important informational messages.  This variable is unset by default.
+If it is set to any value pauses are ignored.
+.TP
+\fBFEATURES\fR = \fI"sandbox ccache"\fR
+Defines actions portage takes by default.  These options should
+not be changed by anyone but developers and/or maintainers.  'sandbox' is an important
+part of \fBFEATURES\fR and should not be disabled by default.  This is 
+an incremental variable.
+.RS
+.TP
+.B assume\-digests
+When commiting work to cvs with \fBrepoman\fR(1), assume that all existing 
+SRC_URI digests are correct.  This feature also affects digest generation via
+\fBebuild\fR(1) and \fBemerge\fR(1) (emerge generates digests only when the
+\fIdigest\fR feature is enabled).
+.TP
+.B buildpkg
+Binary packages will be created for all packages that are merged.
+.TP
+.B buildsyspkg
+Build binary packages for just packages in the system set.
+.TP
+.B ccache
+Enable portage support for the ccache package.  If the ccache dir is not 
+present in the user's environment, then portage will default to 
+${PORTAGE_TMPDIR}/ccache.
+.TP
+.B confcache
+Enable confcache support; global configure caching, speeds up autotool based configure 
+calls via the econf helper function. See \fBebuild\fR(5) for more information.
+.TP
+.B collision\-protect
+A QA\-feature to ensure that a package doesn't overwrite files it doesn't own.
+The \fICOLLISION_IGNORE\fR variable can be used to selectively disable this
+feature.
+.TP
+.B digest
+Autogenerate digests for packages when running the \fBemerge\fR(1) command.  If
+the \fIassume\-digests\fR feature is also enabled then existing SRC_URI digests
+will be reused whenever they are available.
+.TP
+.B distcc
+Enable portage support for the distcc package.
+.TP
+.B distlocks
+Portage uses lockfiles to ensure competing instances don't clobber
+each other's files. This feature is enabled by default but may cause
+heartache on less intelligent remote filesystems like NFSv2 and some
+strangely configured Samba server (oplocks off, NFS re\-export). A tool
+/usr/lib/portage/bin/clean_locks exists to help handle lock issues
+when a problem arises (normally due to a crash or disconnect).
+.TP
+.B fixpackages
+Runs the script that will fix the dependencies in all binary packages.  This is 
+run whenever packages are moved around in the portage tree.  Please note that this 
+can take a lot of time.
+.TP
+.B getbinpkg
+Force emerges to always try to fetch files from the \fIPORTAGE_BINHOST\fR.  See 
+\fBmake.conf\fR(5) for more information.
+.TP
+.B gpg
+Check the signatures of Manifests and make sure they are correct.
+.TP
+.B installsources
+Install source code into /usr/src/debug/${CATEGORY}/${PF} (also see
+\fBsplitdebug\fR). This feature works only if debugedit is installed and CFLAGS
+is set to include debug information (such as with the \-ggdb flag).
+.TP
+.B keeptemp
+Do not delete the ${T} directory after the merge process.
+.TP
+.B keepwork
+Do not delete the ${WORKDIR} directory after the merge process.
+.TP
+.B metadata\-transfer
+Automatically perform a metadata transfer when `emerge \-\-sync` is run.
+.TP
+.B mirror
+This will cause \fBFETCHCOMMAND\fR to always be run even if 
+the file already exists in \fBDISTDIR\fR.
+.TP
+.B noauto
+When utilizing \fBebuild\fR(1), only run the function requested.
+.TP
+.B noclean
+Do not delete the the source and temporary files after the merge process.
+.TP
+.B nodoc
+Do not install doc files (/usr/share/doc).
+.TP
+.B noinfo
+Do not install info pages.
+.TP
+.B noman
+Do not install manpages.
+.TP
+.B nostrip
+Prevents the stripping of binaries that are merged to the live filesystem.
+.TP
+.B notitles
+Disables xterm titlebar updates (which contains status info).
+.TP
+.B parallel\-fetch
+Fetch in the background while compiling.
+.TP
+.B sandbox
+Enable sandbox\-ing when running \fBemerge\fR(1) and \fBebuild\fR(1).
+.TP
+.B severe
+When checking Manifests, only accept ones that have been signed by a
+key which you trust.
+.TP
+.B sfperms
+Stands for Smart Filesystem Permissions.  Before merging packages to the 
+live filesystem, automatically search for and set permissions on setuid 
+and setgid files.  Files that are setuid have the group and other read 
+bits removed while files that are setgid have the other read bit removed.  
+See also \fIsuidctl\fR below.
+.TP
+.B sign
+When commiting work to cvs with \fBrepoman\fR(1), sign the Manifest with 
+a GPG key.  Read about the \fIPORTAGE_GPG_KEY\fR variable in \fBmake.conf\fR(5).
+.TP
+.B splitdebug
+Prior to stripping ELF etdyn and etexec files, the debugging info is 
+stored for later use by various debuggers.  This feature is disabled by
+\fBnostrip\fR.  For installation of source code, see \fBinstallsources\fR.
+.TP
+.B strict
+Have portage react strongly to conditions that have the potential to be 
+dangerous (like missing or incorrect Manifests).
+.TP
+.B stricter
+Have portage react strongly to conditions that may conflict with system
+security provisions (for example textrels, executable stack).  Read about
+the \fIQA_STRICT_*\fR variables in \fBmake.conf\fR(5).
+.TP
+.B suidctl
+Before merging packages to the live filesystem, automatically strip setuid 
+bits from any file that is not listed in \fI/etc/portage/suidctl.conf\fR.
+.TP
+.B test
+Run package\-specific tests during each merge to help make sure 
+the package compiled properly.  See \fItest\fR in \fBebuild\fR(1) 
+and \fIsrc_test()\fR in \fBebuild\fR(5). This feature implies the "test"
+\fBUSE\fR flag.
+.TP
+.B userfetch
+When portage is run as root, drop privileges to portage:portage during the
+fetching of package sources.
+.TP
+.B userpriv
+Allow portage to drop root privileges and compile packages as 
+portage:portage without a sandbox (unless \fIusersandbox\fR is also used).
+.TP
+.B usersandbox
+Enable the sandbox in the compile phase, when running without root privs (\fIuserpriv\fR).
+.RE
+.TP
+.B FETCHCOMMAND
+This variable contains the command used for fetching package sources from
+the internet.  It must contain the full path to the executable as well as the
+place\-holders \\${DISTDIR} and \\${URI}.
+.TP
+\fBGENTOO_MIRRORS\fR = \fI[URLs]\fR
+Insert your space\-seperated list of local mirrors here.  These
+locations are used to download files before the ones listed in
+the \fIebuild scripts\fR. Merging 'mirrorselect' can help.  Entries in this
+variable that have no protocol and simply start with a '/' path separator may
+be used to specify mounted filesystem mirrors.
+.TP
+\fBhttp_proxy ftp_proxy\fR = \fI[host:port]\fR
+These vars are used if the sources must be downloaded from the
+internet by \fBwget\fR(1).  They are only required if you use a
+proxy server for internet access.
+.TP
+\fBINSTALL_MASK\fR = \fI[space delimited list of file names]\fR
+Use this variable if you want to selectively prevent certain files from being
+copied into your file system tree.  This does not work on symlinks, but only on
+actual files.  Useful if you wish to filter out files like HACKING.gz and
+TODO.gz.
+.TP
+.B MAKEOPTS
+Use this variable if you want to use parallel make.  For example, if you
+have a dual\-processor system, set this variable to "\-j2" or "\-j3" for 
+enhanced build performance with many packages. Suggested settings are
+between \fICPUs+1\fR and \fI2*CPUs+1\fR.
+For more information, see \fBmake\fR(1).
+.TP
+\fBNOCOLOR\fR = \fI["true" | "false"]\fR
+Defines if color should be disabled by default.
+.br
+Defaults to false.
+.TP
+\fBPKGDIR\fR = \fI[path]\fR
+Defines the location where created .tbz2 binary packages will be stored.
+.br
+Defaults to ${PORTDIR}/packages.
+.TP
+.B PORT_LOGDIR
+This variable defines the directory in which per\-ebuild logs are kept.
+Logs are created only when this is set and writable.
+.TP
+\fBPORTAGE_BINHOST\fR = \fI"ftp://login:pass@grp.mirror.site/pub/grp/i686/athlon\-xp"\fR
+This is the host from which portage will grab prebuilt\-binary packages.  
+The list is a single entry specifying the full address of the directory 
+serving the tbz2's for your system.  This is only used when running with 
+the get binary pkg options are given to \fBemerge\fR.  Review \fBemerge\fR(1) 
+for more information.  Note that it should point to the 'All' directory on 
+the host that creates the binary packages and not to the root of the \fBPKGDIR\fR.
+.TP
+\fBPORTAGE_COMPRESS\fR = \fI"bzip2"\fR
+This variable contains the command used to compress documentation during the
+install phase.
+.TP
+\fBPORTAGE_COMPRESS_FLAGS\fR = \fI"\-9"\fR
+This variable contains flags for the \fBPORTAGE_COMPRESS\fR command.
+.TP
+.B PORTAGE_ELOG_CLASSES
+.TP
+.B PORTAGE_ELOG_SYSTEM
+.TP
+.B PORTAGE_ELOG_COMMAND
+.TP
+.B PORTAGE_ELOG_MAILURI
+.TP
+.B PORTAGE_ELOG_MAILFROM
+.TP
+.B PORTAGE_ELOG_MAILSUBJECT
+Please see /etc/make.conf.example for elog documentation.
+.TP
+\fBPORTAGE_NICENESS\fR = \fI[number]\fR
+The value of this variable will be added to the current nice level that
+emerge is running at.  In other words, this will not set the nice level,
+it will increment it.  For more information about nice levels and what
+are acceptable ranges, see \fBnice\fR(1).
+.TP
+\fBPORTAGE_RSYNC_EXTRA_OPTS\fR = \fI[rsync options string]\fR
+Additional rsync options to be used by \fBemerge \-\-sync\fR.
+.br
+Defaults to no value.
+.TP
+\fBPORTAGE_RSYNC_OPTS\fR = \fI[rsync options string]\fR
+Default rsync options to be used by \fBemerge \-\-sync\fR. 
+.br
+\fBDon't change this unless you know exactly what you're doing!\fR
+.br
+Defaults to "\-\-recursive \-\-links \-\-safe\-links \-\-perms \-\-times
+\-\-compress \-\-force \-\-whole\-file \-\-delete \-\-delete\-after \-\-stats
+\-\-timeout=180 \-\-exclude='/distfiles' \-\-exclude='/local'
+\-\-exclude='/packages'"
+.TP
+\fBPORTAGE_RSYNC_RETRIES\fR = \fI[NUMBER]\fR
+The number of times rsync should retry on failed connections before
+giving up.
+.br
+Defaults to 3.
+.TP
+\fBPORTAGE_TMPDIR\fR = \fI[path]\fR
+Defines the location of the temporary build directories.
+.br
+Defaults to /var/tmp.
+.TP
+\fBPORTDIR\fR = \fI[path]\fR
+Defines the location of your Portage tree.
+.br
+Defaults to /usr/portage. 
+.br
+\fB***Warning***\fR
+.br
+Storing data such as distfiles and binary packages in PORTDIR can
+be potentially dangerous. The default emerge configuration defaults to this 
+behavior (which will work fine), however if you deviate from the default
+configuration by changing PKGDIR or DISTDIR, emerge \-\-sync may inadvertedly
+delete all your distfiles/binary packages. Please make sure to set
+\fBPORTAGE_EXTRA_RSYNC_OPTS\fR properly to insure the safety of files in PORTDIR.
+.TP
+\fBPORTDIR_OVERLAY\fR = \fI"[path] [different\-path] [etc...]"\fR
+Defines the directories in which user made ebuilds may be stored and not 
+overwriten when `emerge \-\-sync` is run.  This is a space delimited list of 
+directories.
+.br
+Defaults to no value.
+.TP
+\fBQA_STRICT_EXECSTACK = \fI"set"\fR
+Set this to cause portage to ignore any \fIQA_EXECSTACK\fR override
+settings from ebuilds.  See also \fBebuild\fR(5).
+.TP
+\fBQA_STRICT_WX_LOAD = \fI"set"\fR
+Set this to cause portage to ignore any \fIQA_WX_LOAD\fR override
+settings from ebuilds.  See also \fBebuild\fR(5).
+.TP
+\fBQA_STRICT_TEXTRELS = \fI"set"\fR
+Set this to cause portage to ignore any \fIQA_TEXTREL\fR override
+settings from ebuilds.  See also \fBebuild\fR(5).
+.TP
+.B RESUMECOMMAND
+This variable contains the command used for resuming package sources that
+have been partially downloaded.  It should be defined using the same format
+as \fBFETCHCOMMAND\fR.
+.TP
+\fBROOT\fR = \fI[path]\fR
+Use \fBROOT\fR to specify the target root filesystem to be used for merging 
+packages or ebuilds.  All \fBRDEPEND\fR and \fBPDEPEND\fR will be installed 
+into \fBROOT\fR while all \fBDEPEND\fR will be still be installed into /.  
+Typically, you should set this setting in the environment rather than in 
+\fI/etc/make.conf\fR itself.  It's commonly used for creating new build 
+images.  Make sure you use an absolute path.
+.br
+Defaults to /.
+.TP
+\fBRPMDIR\fR = \fI[path]\fR
+Defines the location where created RPM packages will be stored.
+.br
+Defaults to ${PORTDIR}/rpm.
+.TP
+\fBSYNC\fR = \fI[RSYNC]\fR
+Insert your preferred rsync mirror here.  This rsync server
+is used to sync the local portage tree when `emerge \-\-sync` is run.
+.br
+Defaults to rsync://rsync.gentoo.org/gentoo\-portage
+.TP
+\fBUSE\fR = \fI[space delimited list of USE items]\fR
+This variable contains options that control the build behavior of several
+packages.  More information in \fBebuild\fR(5).  Possible USE values
+can be found in \fI/usr/portage/profiles/use.desc\fR.
+.TP
+\fBUSE_EXPAND_HIDDEN\fR = \fI[space delimited list of variable names]\fR
+Names of \fBUSE_EXPAND\fR variables that should not be shown in the verbose merge
+list output of the \fBemerge\fR(1) command.
+.TP
+\fBUSE_ORDER\fR = \fI"env:pkg:conf:defaults:pkginternal"\fR
+Determines the precedence of layers in the incremental stacking of the USE
+variable. Precedence decreases from left to right such that env overrides
+pkg, pkg overrides conf, and so forth.
+
+.B ***warning***
+.br
+Do not modify this value unless you're a developer and you know what
+you're doing. If you change this and something breaks, we will not help
+you fix it.
+.br
+.RS
+.TP
+.B env
+USE from the current USE environment variable if it exists
+.TP
+.B pkg
+Per\-package USE from \fB/etc/portage/package.use\fR (see \fBportage\fR(5))
+.TP
+.B conf
+USE from make.conf
+.TP
+.B defaults
+USE from make.defaults and package.use in the profile (see \fBportage\fR(5))
+.TP
+.B pkginternal
+USE from ebuild IUSE defaults (flags enabled via a + prefix; see \fBebuild\fR(5))
+.RE
+
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "AUTHORS"
+.nf
+Daniel Robbins <drobbins@gentoo.org>
+Nicholas Jones <carpaski@gentoo.org>
+Mike Frysinger <vapier@gentoo.org>
+Saleem Abdulrasool <compnerd@gentoo.org>
+.fi
+.SH "FILES"
+.TP
+\fB/etc/make.conf\fR 
+Contains variables for the build\-process and overwrites those in make.defaults.
+.TP
+\fB/etc/make.globals\fR 
+Contains the default variables for the build\-process, you should edit \fI/etc/make.conf\fR instead.
+.TP
+\fB/usr/portage/profiles/use.desc\fR
+Contains a list of all global USE flags.
+.TP
+\fB/usr/portage/profiles/use.local.desc\fR
+Contains a list of all local USE variables.
+.SH "SEE ALSO"
+.BR emerge (1),
+.BR portage (5),
+.BR ebuild (1),
+.BR ebuild (5)
+.TP
+The \fI/usr/sbin/ebuild.sh\fR script. 
+.TP
+The helper apps in \fI/usr/lib/portage/bin\fR.
Index: /vendor/portage/current/man/portage.5
===================================================================
--- /vendor/portage/current/man/portage.5	(revision 3419)
+++ /vendor/portage/current/man/portage.5	(revision 3419)
@@ -0,0 +1,734 @@
+.TH "PORTAGE" "5" "Dec 2005" "Portage 2.1" "Portage"
+.SH NAME
+portage \- the heart of Gentoo
+.SH "DESCRIPTION"
+The current portage code uses many different configuration files, most of which 
+are unknown to users and normal developers.  Here we will try to collect all 
+the odds and ends so as to help users more effectively utilize portage.  This 
+is a reference only for files which do not already have a man page.
+
+All files in the make.profile directory may be tweaked via parent profiles 
+when using cascading profiles.  For more info, please see 
+http://www.gentoo.org/proj/en/releng/docs/cascading-profiles.xml
+.IP Note:
+If you are looking for information on how to emerge something, please see 
+.BR emerge (1).
+.SH "SYNOPSIS"
+.TP
+.BR /etc/
+.nf
+make.globals
+.BR make.conf (5)
+.fi
+.TP
+.BR /etc/make.profile/
+.nf
+deprecated
+make.defaults
+packages
+packages.build
+package.provided
+package.use
+package.use.force
+package.use.mask
+parent
+profile.bashrc
+use.force
+use.mask
+virtuals
+.fi
+.TP
+.BR /etc/portage/
+.nf
+bashrc
+modules
+package.keywords
+package.mask
+package.unmask
+package.use
+mirrors
+categories
+.fi
+.TP
+.BR /etc/portage/profile/
+site-specific overrides of \fB/etc/make.profile/\fR
+.TP
+.BR /usr/portage/profiles/
+.nf
+arch.list
+categories
+info_pkgs
+info_vars
+package.mask
+profiles.desc
+thirdpartymirrors
+use.desc
+use.local.desc
+.fi
+.TP
+.BR /var/cache/edb/
+misc internal cache files
+.TP
+.BR /var/db/pkg/
+database to track installed packages
+.TP
+.BR /var/lib/portage/
+.nf
+config
+world
+.fi
+.SH "GLOSSARY"
+In the following sections, some terminology may be foreign to you or used 
+with meaning specific to Portage.  Please see the referenced manpages for 
+more detailed explanations.
+.RS
+.TP
+.B DEPEND atom
+A string which matches a package.  It is of the form category/package.  
+It may also contain optional logical operators and versions.
+.br
+More reading: 
+.BR ebuild (5)
+.TP
+.B KEYWORD
+Each architecture has a unique KEYWORD.
+.br
+More reading: 
+.BR ebuild (5)
+.TP
+.B virtual
+A DEPEND atom that is part of the "virtual" category.  They are used 
+when different packages can satisfy a dependency and only one of them is 
+needed.
+.br
+More reading: 
+.BR ebuild (5)
+.RE
+.SH "SPECIFIC FILE DESCRIPTIONS"
+.TP
+.BR /etc/
+.RS
+.TP
+.BR make.globals
+The global default settings for Portage.  This comes from the portage package 
+itself.  Settings in \fBmake.conf\fR override values here.  The format 
+is described extensivly in \fBmake.conf\fR(5).
+.TP
+.BR make.conf
+The global custom settings for Portage.  See \fBmake.conf\fR(5).
+.RE
+.TP
+.BR /etc/make.profile/
+This is usually just a symlink to the correct profile in 
+\fB/usr/portage/profiles/\fR.  Since it is part of the portage tree, it 
+may easily be updated/regenerated by running `emerge \-\-sync`.  It defines 
+what a profile is (usually arch specific stuff).  If you need a custom 
+profile, then you should make your own \fB/etc/make.profile/\fR 
+directory and populate it.  However, if you just wish to override some 
+settings, do NOT edit these files because they WILL be lost with the 
+next `emerge \-\-sync`.  See the section below on \fB/etc/portage/\fR for 
+overriding.
+.RS
+.TP
+.BR deprecated
+The existence of this file marks a profile as deprecated, meaning it is 
+not supported by Gentoo anymore.  The first line must be the profile to which 
+users are encouraged to upgrade, optionally followed by some instructions 
+explaining how they can upgrade.
+
+.I Example:
+.nf
+default-linux/x86/2005.0
+# emerge -n '>=sys-apps/portage-2.0.51'
+# rm -f /etc/make.profile
+# ln -s /usr/portage/profiles/default-linux/alpha/2005.0 /etc/make.profile
+.fi
+.TP
+.BR make.defaults
+The profile default settings for Portage.  The general format is described 
+in \fBmake.conf\fR(5).  The \fImake.defaults\fR for your profile defines a 
+few specific variables too:
+
+.PD 0
+.RS
+.TP
+.BR ARCH
+Architecture type (x86/ppc/hppa/etc...).
+.TP
+.B USERLAND = \fI"GNU"\fR
+Support BSD/cygwin/etc...
+.TP
+.B PORTAGE_LIBC = \fI"glibc"\fR
+Support uClibc/BSD libc/etc...
+.TP
+.BR PROFILE_ARCH
+Distinguish machines classes that have the same \fBARCH\fR.  All sparc 
+machines have ARCH=sparc but set this to either 'sparc32' or 'sparc64'.
+.TP
+.BR STAGE1_USE
+Special USE flags which may be needed when bootstrapping from stage1 to stage2.
+.TP
+.BR GRP_STAGE23_USE
+Special USE flags used by catalyst for building a stage3 and GRP sets.
+.RE
+.PD 1
+.TP
+.BR packages
+This file serves two purposes.  The first is to mask out specific 
+packages/versions on a per\-profile basis.  The second is to provide the 
+list of packages that compose the special \fIsystem\fR set.
+
+.I Format:
+.nf
+\- comments begin with #
+\- one DEPEND atom per line of what to mask OUT
+\- packages to be added to the system set begin with a *
+.fi
+.I Note:
+In a cascading profile setup, you can remove packages in children 
+profiles which were added by parent profiles by prefixing the atom with 
+a '\-'.
+
+.I Example:
+.nf
+# i am a comment !
+# only allow versions of glibc less than 2.3
+<sys\-libs/glibc\-2.3
+# add any version of bash to the system set
+*app\-shells/bash
+# only allow versions of readline earlier than 4.2
+# and add it to the system set
+*<sys\-libs/readline\-4.2
+.fi
+.TP
+.BR packages.build
+A list of packages (one per line) that make up a stage1 tarball.  Really only 
+useful for stage builders.
+.TP
+.BR package.provided
+A list of packages (one per line) that portage should assume have been 
+provided.  Useful for porting to non-Linux systems.  Portage will not 
+attempt to update a package that is listed here unless another package 
+explicitly requires a version that is newer than what has been listed.  
+Basically, it's a list that replaces the \fBemerge \-\-inject\fR syntax.
+
+For example, if you manage your own copy of a 2.6 kernel, then you can 
+tell portage that 'sys-kernel/development-sources-2.6.7' is already taken 
+care of and it should get off your back about it.
+
+Virtual packages (virtual/*) should not be specified in package.provided.
+Depending on the type of virtual, it may be necessary to add an entry to the
+virtuals file and/or add a package that satisfies a virtual to
+package.provided.
+
+.I Format:
+.nf
+\- comments begin with #
+\- one DEPEND atom per line
+\- relational operators are not allowed
+\- must include a version
+.fi
+
+.I Example:
+.nf
+# you take care of the kernel
+sys-kernel/development-sources-2.6.7
+
+# you installed your own special copy of QT
+x11-libs/qt-3.3.0
+
+# you have modular X but packages want monolithic
+x11-base/xorg-x11-6.8
+.fi
+.TP
+.BR package.use.force
+Per\-package USE flag forcing.
+
+.I Note:
+In a cascading profile setup, you can remove USE flags in children 
+profiles which were added by parent profiles by prefixing the flag with 
+a '\-'.
+
+.I Format:
+.nf
+\- comments begin with #
+\- one DEPEND atom per line with space-delimited USE flags
+.fi
+
+.I Example:
+.nf
+# force docs for GTK 2.x
+=x11\-libs/gtk+\-2* doc
+# unforce mysql support for QT
+x11\-libs/qt \-mysql
+.fi
+.TP
+.BR package.use.mask
+Per\-package USE flag masks.
+
+.I Note:
+In a cascading profile setup, you can remove USE flags in children 
+profiles which were added by parent profiles by prefixing the flag with 
+a '\-'.
+
+.I Format:
+.nf
+\- comments begin with #
+\- one DEPEND atom per line with space-delimited USE flags
+.fi
+
+.I Example:
+.nf
+# mask docs for GTK 2.x
+=x11\-libs/gtk+\-2* doc
+# unmask mysql support for QT
+x11\-libs/qt \-mysql
+.fi
+.TP
+.BR parent
+This contains a path to the parent profile.  It may be either relative or 
+absolute.  The paths will be relative to the location of the profile.  Most 
+commonly this file contains '..' to indicate the directory above.  Utilized 
+only in cascading profiles.
+.TP
+.BR profile.bashrc
+If needed, this file can be used to set up a special environment for ebuilds,
+different from the standard root environment.  The syntax is the same as for
+any other bash script.
+.TP
+.BR use.force
+Some USE flags don't make sense to disable under certain conditions.  Here we
+list forced flags.
+
+.I Note:
+In a cascading profile setup, you can remove USE flags in children 
+profiles which were added by parent profiles by prefixing the flag with 
+a '\-'.
+
+.I Format:
+.nf
+\- comments begin with #
+\- one USE flag per line
+.fi
+.TP
+.BR use.mask
+Some USE flags don't make sense on some archs (for example altivec on 
+non\-ppc or mmx on non\-x86), or haven't yet been tested.  Here we list 
+the masked ones.
+
+.I Note:
+In a cascading profile setup, you can remove USE flags in children 
+profiles which were added by parent profiles by prefixing the flag with 
+a '\-'.
+
+.I Format:
+.nf
+\- comments begin with #
+\- one USE flag per line
+.fi
+.TP
+.BR virtuals
+This controls what packages will provide a virtual by default.  For example, 
+if a package needs to send e\-mail, it will need virtual/mta.  In the absence 
+of a package that provides virtual/mta (like qmail, sendmail, postfix, etc...), 
+portage will look here to see what package to use.  In this case, Gentoo uses 
+net\-mail/ssmtp as the default (as defined in the virtuals file) because it's 
+the package that does the very bare minimum to send e\-mail.
+
+.I Format:
+.nf
+\- comments begin with #
+\- one virtual and DEPEND atom base pair per line
+.fi
+
+.I Example:
+.nf
+# use net\-mail/ssmtp as the default mta
+virtual/mta           net\-mail/ssmtp
+# use app\-dicts/aspell\-en as the default dictionary
+virtual/aspell\-dict   app\-dicts/aspell\-en
+.fi
+.RE
+.TP
+.BR /etc/portage/
+Any file in this directory that begins with "package." can be more than just a 
+flat file.  If it is a directory, then all the files in that directory will be 
+summed together as if it were a single file.
+
+.I Example:
+.nf
+/etc/portage/package.keywords/kde
+/etc/portage/package.keywords/common
+/etc/portage/package.keywords/e17
+.fi
+.RS
+.TP
+.BR bashrc
+If needed, this file can be used to set up a special environment for ebuilds,
+different from the standard root environment.  The syntax is the same as for
+any other bash script.
+.TP
+.BR modules
+This file can be used to override the metadata cache implementation.  In
+practice, portdbapi.auxdbmodule is the only variable that the user will want to
+override.
+
+.I Example:
+.nf
+portdbapi.auxdbmodule = cache.metadata_overlay.database
+.fi
+
+The metadata_overlay cache module makes it possible to disable
+FEATURES="metadata-transfer" in \fBmake.conf\fR(5).  When the user initially
+enables metadata_overlay in /etc/portage/modules, all of the cache files
+contained in /var/cache/edb/dep/${PORTDIR} must be manually removed in order
+to avoid unecessary cache regeneration.  In addition, users of the
+metadata_overlay module must never modify eclasses in ${PORTDIR} because
+portage will not be able to detect that cache regeneration is necessary.  If
+the user would like to modify eclasses, it is safe to use metadata_overlay
+together with PORTDIR_OVERLAY in \fBmake.conf\fR.
+.TP
+.BR package.keywords
+Per\-package KEYWORDS.  Useful for mixing unstable packages in with a normally 
+stable system or vice versa.  This will allow ACCEPT_KEYWORDS to be augmented
+for a single package.
+
+.I Format:
+.nf
+\- comment lines begin with # (no inline comments)
+\- one DEPEND atom per line followed by additional KEYWORDS
+\- lines without any KEYWORDS imply unstable host arch
+
+.I Example:
+# always use unstable libgd
+media\-libs/libgd ~x86
+# only use stable mplayer
+media\-video/mplayer \-~x86
+# always use unstable netcat
+net-analyzer/netcat
+.fi
+
+.I Note:
+.fi
+In addition to the normal values from ACCEPT_KEYWORDS package.keywords supports
+three special tokens:
+
+.nf
+\fB*\fR  package is visible if it is stable on any architecture
+\fB~*\fR package is visible if it is in testing on any architecture
+\fB**\fR package is always visible (KEYWORDS are ignored completely)
+.fi
+
+.I Additional Note:
+If you encounter the \fB-*\fR KEYWORD, this indicates that the package is known 
+to be broken on all systems which are not otherwise listed in KEYWORDS.  For 
+example, a binary only package which is built for x86 will look like:
+
+games-fps/quake3-demo-1.11.ebuild:KEYWORDS="-* x86"
+
+If you wish to accept this package anyways, then use one of the other keywords in your 
+package.keywords like this:
+
+games-fps/quake3-demo x86
+
+.TP
+.BR package.mask
+A list of package atoms to mask.  Useful if specific versions of packages do
+not work well for you.  For example, you swear by the Nvidia drivers, but only
+versions earlier than 1.0.4496.  No problem!
+
+.I Format:
+.nf
+\- comment lines begin with # (no inline comments)
+\- one DEPEND atom per line
+.fi
+
+.I Example:
+.nf
+# mask out versions 1.0.4496 of the nvidia
+# drivers and later
+>=media\-video/nvidia\-kernel\-1.0.4496
+>=media\-video/nvidia\-glx\-1.0.4496
+.fi
+.TP
+.BR package.unmask
+Just like package.mask above, except here you list packages you want to 
+unmask.  Useful for overriding the global package.mask file (see 
+below).  Note that this does not override packages that are masked via 
+KEYWORDS.
+.TP
+.BR package.use
+Per\-package USE flags.  Useful for tracking local USE flags or for 
+enabling USE flags for certain packages only.  Perhaps you develop GTK 
+and thus you want documentation for it, but you don't want 
+documentation for QT.  Easy as pie my friend!
+
+.I Format:
+.nf
+\- comments begin with #
+\- one DEPEND atom per line with space-delimited USE flags
+.fi
+
+.I Example:
+.nf
+# turn on docs for GTK 2.x
+=x11\-libs/gtk+\-2* doc
+# disable mysql support for QT
+x11\-libs/qt \-mysql
+.fi
+.TP
+.BR mirrors
+Whenever portage encounters a mirror:// style URL it will look up the actual 
+hosts here.  If the mirror set is not found here, it will check the global 
+mirrors file at /usr/portage/profiles/thirdpartymirrors.  You may also set a 
+special mirror type called "local".  This list of mirrors will be checked 
+before GENTOO_MIRRORS and will be used even if the package has 
+RESTRICT="mirror" or RESTRICT="fetch".
+
+.I Format:
+.nf
+\- comments begin with #
+\- mirror type followed by a list of hosts
+.fi
+
+.I Example:
+.nf
+# local private mirrors used only by my company
+local ftp://192.168.0.3/mirrors/gentoo http://192.168.0.4/distfiles
+
+# people in japan would want to use the japanese mirror first
+sourceforge http://keihanna.dl.sourceforge.net/sourceforge
+
+# people in tawain would want to use the local gnu mirror first
+gnu ftp://ftp.nctu.edu.tw/UNIX/gnu/
+.fi
+.TP
+.BR categories
+A simple list of valid categories that may be used in /usr/portage, 
+PORTDIR_OVERLAY, and PKGDIR (see \fBmake.conf\fR(5)).  This allows for custom 
+categories to be created.
+
+.I Format:
+.nf
+\- one category per line
+.fi
+
+.I Example:
+.nf
+app\-hackers
+media\-other
+.fi
+.RE
+.TP
+.BR /usr/portage/profiles/
+Global Gentoo settings that are controlled by the developers.  To override 
+these settings, you can use the files in \fB/etc/portage/\fR.
+.RS
+.TP
+.BR arch.list
+A list of all valid KEYWORDS.  This does not include modifiers.
+
+.I Format:
+.nf
+\- one KEYWORD per line
+.fi
+
+.I Example:
+.nf
+x86
+ppc
+sparc
+.fi
+.TP
+.BR categories
+A simple list of valid categories that may be used in /usr/portage, 
+PORTDIR_OVERLAY, and PKGDIR (see \fBmake.conf\fR(5)).
+
+.I Format:
+.nf
+\- one category per line
+.fi
+
+.I Example:
+.nf
+app\-admin
+dev\-lang
+games\-strategy
+sys\-kernel
+.fi
+.TP
+.BR info_pkgs
+A list of all the packages which will be displayed when you run `emerge info`.
+.TP
+.BR info_vars
+A list of all the variables which will be displayed when you run `emerge info`.
+.TP
+.BR package.mask
+This contains a list of DEPEND atoms for packages that should not be installed 
+in any profile.  Useful for adding the latest KDE betas and making sure no 
+one accidentally upgrades to them.  Also useful for quickly masking specific 
+versions due to security issues.  ALWAYS include a comment explaining WHY the 
+package has been masked and WHO is doing the masking.
+
+.I Format:
+.nf
+\- comments begin with #
+\- one DEPEND atom per line
+.fi
+
+.I Example:
+.nf
+# masked for security reasons
+<sys\-libs/zlib\-1.1.4
+# <caleb@gentoo.org> (10 Sep 2003)
+# new kde betas
+=kde\-base/kde\-3.2.0_beta1
+=kde\-base/kdeaccessibility\-3.2.0_beta1
+.fi
+.TP
+.BR profiles.desc
+List all the current stable and development profiles.  If a profile is listed 
+here, then it will be checked by repoman.  At the moment, only 1 profile is 
+allowed per stable/dev/KEYWORD; the last one found is the last one used.
+
+.I Format:
+.nf
+\- comments begin with #
+\- one profile list per line in format: arch dir status
+\- arch must be listed in arch.list
+\- dir is relative to profiles.desc
+\- status must be 'stable' or 'dev'
+.fi
+
+.I Example:
+.nf
+alpha default-linux/alpha/2004.3 stable
+m68k  default-linux/m68k         dev
+x86   default-linux/x86/2004.3   stable
+.fi
+.TP
+.BR thirdpartymirrors
+Controls the mapping of mirror:// style URLs to actual lists of 
+mirrors.  Keeps us from overloading a single server.
+
+.I Format:
+.nf
+\- comments begin with #
+\- mirror type followed by a list of hosts
+.fi
+
+.I Example:
+.nf
+sourceforge http://aleron.dl.sourceforge.net/sourceforge http://unc.dl.sourceforge.net/sourceforge
+
+gentoo http://distro.ibiblio.org/pub/linux/distributions/gentoo/distfiles/ ftp://ftp.gtlib.cc.gatech.edu/pub/gentoo/distfiles
+
+kernel http://www.kernel.org/pub http://www.us.kernel.org/pub
+.fi
+.TP
+.BR use.desc
+All global USE flags must be listed here with a description of what they do.  
+
+.I Format:
+.nf
+\- comments begin with #
+\- use flag \- some description
+.fi
+
+.I Example:
+.nf
+3dfx \- Adds support for 3dfx video cards
+acl \- Adds support for Access Control Lists
+doc \- Adds extra documentation
+.fi
+.TP
+.BR use.local.desc
+All local USE flags must be listed here along with the package and a 
+description.
+
+.nf
+.I Format:
+\- comments begin with #
+\- package:use flag \- description
+
+.I Example:
+app\-editors/nano:justify \- Toggles the justify option
+dev\-libs/DirectFB:fusion \- Adds Multi Application support
+games\-emulation/xmess:net \- Adds network support
+.fi
+.RE
+.TP
+.BR /var/cache/edb/
+.RS
+This directory is used to store internal portage cache files.  The names and
+purpose of these files are not documented on purpose so as to keep down bitrot
+as internals change.  If you aren't working on portage internally, then the
+details most likely do not matter to you.
+
+This entire directory can be safely deleted.  It is highly recommended you do
+not do this however as it can be a time consuming process to generate them all
+again.
+.RE
+.TP
+.BR /var/db/pkg/
+.RS
+All installed package information is recorded here.  If portage thinks you have
+a package installed, it is usually because it is listed here.
+
+The format follows somewhat closely that of the portage tree.  There is a
+directory for each category and a package-version subdirectory for each package
+you have installed.
+
+Inside each package directory are misc files that describe the installed
+contents of the package as well as build time information (so that the package
+can be unmerged without needing the portage tree).
+
+The exact file contents and format are not described here again so that things
+can be changed quickly.  Generally though there is one file per environment
+variable that "matters" (like CFLAGS) with the contents stored inside of it.
+Another common file is the CONTENTS file which lists the path and hashes of
+all objects that the package installed onto your system.
+.RE
+.TP
+.BR /var/lib/portage/
+.RS
+.TP
+.BR config
+Hashes which are used to determine whether files in config protected
+directories have been modified since being installed.  Files which have not
+been modified will automatically be unmerged.
+.TP
+.BR world
+Every time you emerge a package, the package that you requested is 
+recorded here.  Then when you run `emerge world \-up`, the list of 
+packages is read from this file.  Note that this does not mean that the 
+packages that were installed as dependencies are listed here.  For 
+example, if you run `emerge mod_php` and you do not have apache 
+already, then "dev\-php/mod_php" is recorded in the world file but 
+"net\-www/apache" is not.  For more information, review \fBemerge\fR(1).
+
+.I Format:
+.nf
+\- one DEPEND atom base per line
+.fi
+
+.I Example:
+.nf
+games\-misc/fortune\-mod\-gentoo\-dev
+dev\-libs/uclibc
+app\-cdr/cdemu
+.fi
+.RE
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH "AUTHORS"
+.nf
+Marius Mauch <genone@gentoo.org>
+Mike Frysinger <vapier@gentoo.org>
+Drake Wyrm <wyrm@haell.com>
+.fi
+.SH "SEE ALSO"
+.BR emerge (1),
+.BR ebuild (1),
+.BR ebuild (5),
+.BR make.conf (5)
Index: /vendor/portage/current/man/quickpkg.1
===================================================================
--- /vendor/portage/current/man/quickpkg.1	(revision 3419)
+++ /vendor/portage/current/man/quickpkg.1	(revision 3419)
@@ -0,0 +1,55 @@
+.TH "QUICKPKG" "1" "Dec 2005" "Portage 2.1" "Portage"
+.SH NAME
+quickpkg \- creates portage packages
+.SH SYNOPSIS
+.B quickpkg <list of pkgs>
+.SH DESCRIPTION
+.I quickpkg
+can be utilized to quickly create a package for portage by
+utilizing the files already on your filesystem.  This package
+then can be emerged on any system.  To review syntax for 
+emerging binary packages, review \fBemerge\fR(1).  The upside
+of this process is that you don't have to wait for the package 
+to unpack, configure, compile, and install before you can have 
+the package ready to go.  The downside is that the package will 
+contain the files that exist on your filesystem even if they have 
+modified since they were first installed.
+.br
+The packages, after being created, will be placed in \fBPKGDIR\fR.  
+This variable is defined in \fBmake.conf\fR(5) and defaults to 
+/usr/portage/packages.
+.SH OPTIONS
+.TP
+.B <list of packages>
+Each package in the list can be of two forms.  First you can
+give it the full path to the installed entry in the virtual
+database.  That is, /var/db/pkg/<CATEGORY>/<PKG-VERSION>/.  
+The second form is a portage depend atom.  This atom is of
+the same form that you would give \fBemerge\fR if you wanted 
+to emerge something.  See \fBebuild\fR(5) for full definition.
+.SH "EXAMPLES"
+.B quickpkg
+/var/db/pkg/dev-python/pyogg-1.1
+.br
+.B quickpkg
+planeshift
+.br
+.B quickpkg
+=apache-1.3.27-r1
+.br
+.B quickpkg
+=net-www/apache-2*
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH AUTHORS
+.nf
+Terry Chan (original author)
+Mike Frysinger <vapier@gentoo.org> (revamped version)
+.fi
+.SH "FILES"
+.TP
+.B /etc/make.conf
+The \fBPKGDIR\fR variable is defined here.
+.SH "SEE ALSO"
+.BR ebuild (5),
+.BR make.conf (5)
Index: /vendor/portage/current/man/repoman.1
===================================================================
--- /vendor/portage/current/man/repoman.1	(revision 3419)
+++ /vendor/portage/current/man/repoman.1	(revision 3419)
@@ -0,0 +1,265 @@
+.TH "REPOMAN" "1" "Dec 2005" "Portage 2.1" "Portage"
+.SH NAME
+repoman \- Gentoo's program to enforce a minimal level of quality assurance in packages added to the portage tree
+.SH SYNOPSIS
+\fBrepoman\fR [\fIoption\fR] [\fImode\fR]
+.SH DESCRIPTION
+.BR "Quality is job zero."
+
+.BR repoman
+is meant for Gentoo developers only due to the fact it does not work on a per-ebuild basis.
+It checks the quality of CVS repositories.
+
+Note: \fBrepoman commit\fR only works \fIinside local\fR CVS repositories.
+.SH OPTIONS
+.TP
+\fB-q\fR, \fB--quiet\fR
+Be less verbose about extraneous info
+.TP
+\fB-p\fR, \fB--pretend\fR
+Don't commit or fix anything; just show what would be done
+.TP
+\fB-i\fR, \fB--include-masked\fR
+Include masked packages in scans at category or tree level
+.TP
+\fB-x\fR, \fB--xmlparse\fR
+Forces the metadata.xml parse check to be carried out
+.TP
+\fB-v\fR, \fB--verbose\fR
+Displays every package name while checking
+.TP
+\fB-I\fR, \fB--ignore-arches\fR
+Ignore arch-specific failures (where arch != host)
+.TP
+\fB-m\fR, \fB--commitmsg\fR
+Adds a commit message via the command line
+.TP
+\fB-M\fR, \fB--commitmsgfile\fR
+Adds a commit message from the specified file
+.TP
+\fB-V\fR, \fB--version\fR
+Show version info
+.TP
+\fB-h\fR, \fB--help\fR
+Show this screen
+.SH MODES
+.TP
+.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
+.B scan
+Scan directory tree for QA issues (default)
+.TP
+.B fix
+Fix simple QA issues (stray digests, missing digests)
+.TP
+.B lfull
+Remember report from last run (full listing)
+.TP
+.B commit
+Scan directory tree for QA issues; if OK, commit via cvs
+.SH QA KEYWORDS
+.TP
+.B CVS/Entries.IO_error
+Attempting to commit, and an IO error was encountered access the Entries file
+.TP
+.B DEPEND.bad
+User-visible ebuilds with bad DEPEND settings (matched against *visible* ebuilds)
+.TP
+.B DEPEND.badindev
+User-visible ebuilds with bad DEPEND settings (matched against *visible* ebuilds) in developing arch
+.TP
+.B DEPEND.badmasked
+Masked ebuilds with bad DEPEND settings (matched against *all* ebuilds)
+.TP
+.B DEPEND.badmaskedindev
+Masked ebuilds with bad DEPEND settings (matched against *all* ebuilds) in developing arch
+.TP
+.B DEPEND.syntax
+Syntax error in DEPEND (usually an extra/missing space/parenthesis)
+.TP
+.B DESCRIPTION.missing
+Ebuilds that have a missing or empty DESCRIPTION variable
+.TP
+.B HOMEPAGE.missing
+Ebuilds that have a missing or empty HOMEPAGE variable
+.TP
+.B IUSE.invalid
+This build has a variable in IUSE that is not in the use.desc or use.local.desc file
+.TP
+.B KEYWORDS.invalid
+This ebuild contains KEYWORDS that are not listed in profiles/arch.list or for which no valid profile was found
+.TP
+.B KEYWORDS.missing
+Ebuilds that have a missing or empty KEYWORDS variable
+.TP
+.B KEYWORDS.stupid
+Ebuilds that use KEYWORDS=-* instead of package.mask
+.TP
+.B LICENSE.invalid
+This ebuild is listing a license that doesnt exist in portages license/ dir.
+.TP
+.B LICENSE.missing
+Ebuilds that have a missing or empty LICENSE variable
+.TP
+.B LICENSE.syntax
+Syntax error in LICENSE (usually an extra/missing space/parenthesis)
+.TP
+.B LIVEVCS.stable
+Ebuild is a live ebuild (cvs, git, darcs, svn, etc) checkout with stable keywords.
+.TP
+.B PDEPEND.bad
+User-visible ebuilds with bad PDEPEND settings (matched against *visible* ebuilds)
+.TP
+.B PDEPEND.badindev
+User-visible ebuilds with bad PDEPEND settings (matched against *visible* ebuilds) in developing arch
+.TP
+.B PDEPEND.badmasked
+Masked ebuilds with PDEPEND settings (matched against *all* ebuilds)
+.TP
+.B PDEPEND.badmaskedindev
+Masked ebuilds with PDEPEND settings (matched against *all* ebuilds) in developing arch
+.TP
+.B PDEPEND.syntax
+Syntax error in PDEPEND (usually an extra/missing space/parenthesis)
+.TP
+.B PROVIDE.syntax
+Syntax error in PROVIDE (usually an extra/missing space/parenthesis)
+.TP
+.B RDEPEND.bad
+User-visible ebuilds with bad RDEPEND settings (matched against *visible* ebuilds)
+.TP
+.B RDEPEND.badindev
+User-visible ebuilds with bad RDEPEND settings (matched against *visible* ebuilds) in developing arch
+.TP
+.B RDEPEND.badmasked
+Masked ebuilds with RDEPEND settings (matched against *all* ebuilds)
+.TP
+.B RDEPEND.badmaskedindev
+Masked ebuilds with RDEPEND settings (matched against *all* ebuilds) in developing arch
+.TP
+.B RDEPEND.syntax
+Syntax error in RDEPEND (usually an extra/missing space/parenthesis)
+.TP
+.B SLOT.missing
+Ebuilds that have a missing or empty SLOT variable
+.TP
+.B changelog.missing
+Missing ChangeLog files
+.TP
+.B changelog.notadded
+ChangeLogs that exist but have not been added to cvs
+.TP
+.B digest.assumed
+Existing digest must be assumed correct (Package level only)
+.TP
+.B digest.disjointed
+Digests not added to cvs when the matching ebuild has been added
+.TP
+.B digest.fail
+Digest does not match the specified local file
+.TP
+.B digest.missing
+Digest files that are missing (ebuild exists, digest doesn't)
+.TP
+.B digest.notadded
+Digests that exist but have not been added to cvs
+.TP
+.B digest.partial
+Digest files do not contain all corresponding URI elements
+.TP
+.B digest.stray
+Digest files that do not have a corresponding ebuild
+.TP
+.B digest.unmatch
+Digests which are incomplete (please check if your USE/ARCH includes all files)
+.TP
+.B digest.unused
+Digest/Manifest entry has no matching SRC_URI entry
+.TP
+.B ebuild.allmasked
+All ebuilds are masked for this package (Package level only)
+.TP
+.B ebuild.badheader
+This ebuild has a malformed header
+.TP
+.B ebuild.disjointed
+Ebuilds not added to cvs when the matching digest has been added
+.TP
+.B ebuild.invalidname
+Ebuild files with a non-parseable or syntactically incorrect name (or using 2.1 versioning extensions)
+.TP
+.B ebuild.majorsyn
+This ebuild has a major syntax error that may cause the ebuild to fail partially or fully
+.TP
+.B ebuild.minorsyn
+This ebuild has a minor syntax error that contravenes gentoo coding style
+.TP
+.B ebuild.namenomatch
+Ebuild files that do not have the same name as their parent directory
+.TP
+.B ebuild.nesteddie
+Placing 'die' inside ( ) prints an error, but doesn't stop the ebuild.
+.TP
+.B ebuild.nostable
+There are no ebuilds that are marked as stable for your ARCH
+.TP
+.B ebuild.notadded
+Ebuilds that exist but have not been added to cvs
+.TP
+.B ebuild.output
+A simple sourcing of the ebuild produces output; this breaks ebuild policy.
+.TP
+.B ebuild.syntax
+Error generating cache entry for ebuild; typically caused by ebuild syntax error
+.TP
+.B file.UTF8
+File is not UTF8 compliant
+.TP
+.B file.executable
+Ebuilds, digests, metadata.xml, Manifest, and ChangeLog do note need the executable bit
+.TP
+.B file.name
+File/dir name must be composed of only the following chars: a-zA-Z0-9._-+:
+.TP
+.B file.size
+Files in the files directory must be under 20k
+.TP
+.B filedir.missing
+Package lacks a files directory
+.TP
+.B metadata.bad
+Bad metadata.xml files
+.TP
+.B metadata.missing
+Missing metadata.xml files
+.TP
+.B usage.obsolete
+The ebuild makes use of an obsolete construct
+.TP
+.B variable.readonly
+Assigning a readonly variable
+.TP
+.B virtual.exists
+PROVIDE contains existing package names
+.TP
+.B virtual.unavailable
+PROVIDE contains a virtual which contains no profile default
+.TP
+.B virtual.versioned
+PROVIDE contains virtuals with versions
+.SH "REPORTING BUGS"
+Please report bugs via http://bugs.gentoo.org/
+.SH AUTHORS
+.nf
+Daniel Robbins <drobbins@gentoo.org>
+Saleem Abdulrasool <compnerd@gentoo.org>
+.fi
+.SH "SEE ALSO"
+.BR emerge (1)
Index: /vendor/portage/current/pym/cache/__init__.py
===================================================================
--- /vendor/portage/current/pym/cache/__init__.py	(revision 3419)
+++ /vendor/portage/current/pym/cache/__init__.py	(revision 3419)
@@ -0,0 +1,5 @@
+# Copyright: 2005 Gentoo Foundation
+# Author(s): Brian Harring (ferringb@gentoo.org)
+# License: GPL2
+# $Id: __init__.py 3483 2006-06-10 21:40:40Z genone $
+
Index: /vendor/portage/current/pym/cache/anydbm.py
===================================================================
--- /vendor/portage/current/pym/cache/anydbm.py	(revision 3419)
+++ /vendor/portage/current/pym/cache/anydbm.py	(revision 3419)
@@ -0,0 +1,72 @@
+# Copyright: 2005 Gentoo Foundation
+# Author(s): Brian Harring (ferringb@gentoo.org)
+# License: GPL2
+# $Id: anydbm.py 4821 2006-10-26 08:10:35Z zmedico $
+
+anydbm_module = __import__("anydbm")
+try:
+	import cPickle as pickle
+except ImportError:
+	import pickle
+import os
+from cache import fs_template
+from cache import cache_errors
+
+
+class database(fs_template.FsBased):
+
+	autocommits = True
+	cleanse_keys = True
+	serialize_eclasses = False
+
+	def __init__(self, *args, **config):
+		super(database,self).__init__(*args, **config)
+
+		default_db = config.get("dbtype","anydbm")
+		if not default_db.startswith("."):
+			default_db = '.' + default_db
+
+		self._db_path = os.path.join(self.location, fs_template.gen_label(self.location, self.label)+default_db)
+		self.__db = None
+		try:
+			self.__db = anydbm_module.open(self._db_path, "w", self._perms)
+				
+		except anydbm_module.error:
+			# XXX handle this at some point
+			try:
+				self._ensure_dirs()
+				self._ensure_dirs(self._db_path)
+			except (OSError, IOError), e:
+				raise cache_errors.InitializationError(self.__class__, e)
+
+			# try again if failed
+			try:
+				if self.__db == None:
+					self.__db = anydbm_module.open(self._db_path, "c", self._perms)
+			except anydbm_module.error, e:
+				raise cache_errors.InitializationError(self.__class__, e)
+		self._ensure_access(self._db_path)
+
+	def iteritems(self):
+		return self.__db.iteritems()
+
+	def _getitem(self, cpv):
+		# we override getitem because it's just a cpickling of the data handed in.
+		return pickle.loads(self.__db[cpv])
+
+	def _setitem(self, cpv, values):
+		self.__db[cpv] = pickle.dumps(values,pickle.HIGHEST_PROTOCOL)
+
+	def _delitem(self, cpv):
+		del self.__db[cpv]
+
+	def iterkeys(self):
+		return iter(self.__db.keys())
+
+	def __contains__(self, cpv):
+		return cpv in self.__db
+
+	def __del__(self):
+		if "__db" in self.__dict__ and self.__db != None:
+			self.__db.sync()
+			self.__db.close()
Index: /vendor/portage/current/pym/cache/cache_errors.py
===================================================================
--- /vendor/portage/current/pym/cache/cache_errors.py	(revision 3419)
+++ /vendor/portage/current/pym/cache/cache_errors.py	(revision 3419)
@@ -0,0 +1,41 @@
+# Copyright: 2005 Gentoo Foundation
+# Author(s): Brian Harring (ferringb@gentoo.org)
+# License: GPL2
+# $Id: cache_errors.py 3483 2006-06-10 21:40:40Z genone $
+
+class CacheError(Exception):	pass
+
+class InitializationError(CacheError):
+	def __init__(self, class_name, error):
+		self.error, self.class_name = error, class_name
+	def __str__(self):
+		return "Creation of instance %s failed due to %s" % \
+			(self.class_name, str(self.error))
+
+
+class CacheCorruption(CacheError):
+	def __init__(self, key, ex):
+		self.key, self.ex = key, ex
+	def __str__(self):
+		return "%s is corrupt: %s" % (self.key, str(self.ex))
+
+
+class GeneralCacheCorruption(CacheError):
+	def __init__(self,ex):	self.ex = ex
+	def __str__(self):	return "corruption detected: %s" % str(self.ex)
+
+
+class InvalidRestriction(CacheError):
+	def __init__(self, key, restriction, exception=None):
+		if exception == None:	exception = ''
+		self.key, self.restriction, self.ex = key, restriction, ex
+	def __str__(self):
+		return "%s:%s is not valid: %s" % \
+			(self.key, self.restriction, str(self.ex))
+
+
+class ReadOnlyRestriction(CacheError):
+	def __init__(self, info=''):
+		self.info = info
+	def __str__(self):
+		return "cache is non-modifiable"+str(self.info)
Index: /vendor/portage/current/pym/cache/flat_hash.py
===================================================================
--- /vendor/portage/current/pym/cache/flat_hash.py	(revision 3419)
+++ /vendor/portage/current/pym/cache/flat_hash.py	(revision 3419)
@@ -0,0 +1,128 @@
+# Copyright: 2005 Gentoo Foundation
+# Author(s): Brian Harring (ferringb@gentoo.org)
+# License: GPL2
+# $Id: flat_hash.py 5354 2006-12-22 23:26:48Z zmedico $
+
+from cache import fs_template
+from cache import cache_errors
+import errno, os, stat
+from cache.template import reconstruct_eclasses
+# store the current key order *here*.
+class database(fs_template.FsBased):
+
+	autocommits = True
+
+	def __init__(self, *args, **config):
+		super(database,self).__init__(*args, **config)
+		self.location = os.path.join(self.location, 
+			self.label.lstrip(os.path.sep).rstrip(os.path.sep))
+
+		if not self.readonly and not os.path.exists(self.location):
+			self._ensure_dirs()
+
+	def __getitem__(self, cpv):
+		fp = os.path.join(self.location, cpv)
+		try:
+			myf = open(fp, "r")
+			try:
+				d = self._parse_data(myf, cpv)
+				if "_mtime_" not in d:
+					"""Backward compatibility with old cache that uses mtime
+					mangling."""
+					d["_mtime_"] = long(os.fstat(myf.fileno()).st_mtime)
+				return d
+			finally:
+				myf.close()
+		except (IOError, OSError), e:
+			if e.errno != errno.ENOENT:
+				raise cache_errors.CacheCorruption(cpv, e)
+			raise KeyError(cpv)
+
+	def _parse_data(self, data, cpv):
+		try:
+			d = dict(map(lambda x:x.rstrip("\n").split("=", 1), data))
+		except ValueError, e:
+			# If a line is missing an "=", the split length is 1 instead of 2.
+			raise cache_errors.CacheCorruption(cpv, e)
+		if "_eclasses_" in d:
+			d["_eclasses_"] = reconstruct_eclasses(cpv, d["_eclasses_"])
+		return d
+		
+		for x in self._known_keys:
+			if x not in d:
+				d[x] = ''
+
+
+		return d
+
+
+	def _setitem(self, cpv, values):
+#		import pdb;pdb.set_trace()
+		s = cpv.rfind("/")
+		fp = os.path.join(self.location,cpv[:s],".update.%i.%s" % (os.getpid(), cpv[s+1:]))
+		try:	myf=open(fp, "w")
+		except (IOError, OSError), e:
+			if errno.ENOENT == e.errno:
+				try:
+					self._ensure_dirs(cpv)
+					myf=open(fp,"w")
+				except (OSError, IOError),e:
+					raise cache_errors.CacheCorruption(cpv, e)
+			else:
+				raise cache_errors.CacheCorruption(cpv, e)
+
+		for k, v in values.iteritems():
+			if k != "_mtime_" and (k == "_eclasses_" or k in self._known_keys):
+				myf.write("%s=%s\n" % (k, v))
+
+		myf.close()
+		self._ensure_access(fp, mtime=values["_mtime_"])
+
+		#update written.  now we move it.
+
+		new_fp = os.path.join(self.location,cpv)
+		try:	os.rename(fp, new_fp)
+		except (OSError, IOError), e:
+			os.remove(fp)
+			raise cache_errors.CacheCorruption(cpv, e)
+
+
+	def _delitem(self, cpv):
+#		import pdb;pdb.set_trace()
+		try:
+			os.remove(os.path.join(self.location,cpv))
+		except OSError, e:
+			if errno.ENOENT == e.errno:
+				raise KeyError(cpv)
+			else:
+				raise cache_errors.CacheCorruption(cpv, e)
+
+
+	def __contains__(self, cpv):
+		return os.path.exists(os.path.join(self.location, cpv))
+
+
+	def iterkeys(self):
+		"""generator for walking the dir struct"""
+		dirs = [self.location]
+		len_base = len(self.location)
+		while len(dirs):
+			try:
+				dir_list = os.listdir(dirs[0])
+			except OSError, e:
+				if e.errno != errno.ENOENT:
+					raise
+				del e
+				dirs.pop(0)
+				continue
+			for l in dir_list:
+				if l.endswith(".cpickle"):
+					continue
+				p = os.path.join(dirs[0],l)
+				st = os.lstat(p)
+				if stat.S_ISDIR(st.st_mode):
+					dirs.append(p)
+					continue
+				yield p[len_base+1:]
+			dirs.pop(0)
+
Index: /vendor/portage/current/pym/cache/flat_list.py
===================================================================
--- /vendor/portage/current/pym/cache/flat_list.py	(revision 3419)
+++ /vendor/portage/current/pym/cache/flat_list.py	(revision 3419)
@@ -0,0 +1,106 @@
+from cache import fs_template
+from cache import cache_errors
+import errno, os, stat
+
+# store the current key order *here*.
+class database(fs_template.FsBased):
+
+	autocommits = True
+
+	# do not screw with this ordering. _eclasses_ needs to be last
+	auxdbkey_order=('DEPEND', 'RDEPEND', 'SLOT', 'SRC_URI',
+		'RESTRICT',  'HOMEPAGE',  'LICENSE', 'DESCRIPTION',
+		'KEYWORDS',  'IUSE', 'CDEPEND',
+		'PDEPEND',   'PROVIDE','_eclasses_')
+
+	def __init__(self, label, auxdbkeys, **config):
+		super(database,self).__init__(label, auxdbkeys, **config)
+		self._base = os.path.join(self._base, 
+			self.label.lstrip(os.path.sep).rstrip(os.path.sep))
+
+		if len(self._known_keys) > len(self.auxdbkey_order) + 2:
+			raise Exception("less ordered keys then auxdbkeys")
+		if not os.path.exists(self._base):
+			self._ensure_dirs()
+
+
+	def _getitem(self, cpv):
+		d = {}
+		try:
+			myf = open(os.path.join(self._base, cpv),"r")
+			for k,v in zip(self.auxdbkey_order, myf):
+				d[k] = v.rstrip("\n")
+		except (OSError, IOError),e:
+			if errno.ENOENT == e.errno:
+				raise KeyError(cpv)
+			raise cache_errors.CacheCorruption(cpv, e)
+
+		try:
+			d["_mtime_"] = long(os.fstat(myf.fileno()).st_mtime)
+		except OSError, e:	
+			myf.close()
+			raise cache_errors.CacheCorruption(cpv, e)
+		myf.close()
+		return d
+
+
+	def _setitem(self, cpv, values):
+		s = cpv.rfind("/")
+		fp=os.path.join(self._base,cpv[:s],".update.%i.%s" % (os.getpid(), cpv[s+1:]))
+		try:	myf=open(fp, "w")
+		except (OSError, IOError), e:
+			if errno.ENOENT == e.errno:
+				try:
+					self._ensure_dirs(cpv)
+					myf=open(fp,"w")
+				except (OSError, IOError),e:
+					raise cache_errors.CacheCorruption(cpv, e)
+			else:
+				raise cache_errors.CacheCorruption(cpv, e)
+		
+
+		for x in self.auxdbkey_order:
+			myf.write(values.get(x,"")+"\n")
+
+		myf.close()
+		self._ensure_access(fp, mtime=values["_mtime_"])
+		#update written.  now we move it.
+		new_fp = os.path.join(self._base,cpv)
+		try:	os.rename(fp, new_fp)
+		except (OSError, IOError), e:
+			os.remove(fp)
+			raise cache_errors.CacheCorruption(cpv, e)
+
+
+	def _delitem(self, cpv):
+		try:
+			os.remove(os.path.join(self._base,cpv))
+		except OSError, e:
+			if errno.ENOENT == e.errno:
+				raise KeyError(cpv)
+			else:
+				raise cache_errors.CacheCorruption(cpv, e)
+
+
+	def __contains__(self, cpv):
+		return os.path.exists(os.path.join(self._base, cpv))
+
+
+	def iterkeys(self):
+		"""generator for walking the dir struct"""
+		dirs = [self._base]
+		len_base = len(self._base)
+		while len(dirs):
+			for l in os.listdir(dirs[0]):
+				if l.endswith(".cpickle"):
+					continue
+				p = os.path.join(dirs[0],l)
+				st = os.lstat(p)
+				if stat.S_ISDIR(st.st_mode):
+					dirs.append(p)
+					continue
+				yield p[len_base+1:]
+			dirs.pop(0)
+
+
+	def commit(self):	pass
Index: /vendor/portage/current/pym/cache/fs_template.py
===================================================================
--- /vendor/portage/current/pym/cache/fs_template.py	(revision 3419)
+++ /vendor/portage/current/pym/cache/fs_template.py	(revision 3419)
@@ -0,0 +1,74 @@
+# Copyright: 2005 Gentoo Foundation
+# Author(s): Brian Harring (ferringb@gentoo.org)
+# License: GPL2
+# $Id: fs_template.py 4470 2006-09-18 03:54:07Z zmedico $
+
+import os
+from cache import template
+from portage_data import portage_gid
+
+class FsBased(template.database):
+	"""template wrapping fs needed options, and providing _ensure_access as a way to 
+	attempt to ensure files have the specified owners/perms"""
+
+	def __init__(self, *args, **config):
+		"""throws InitializationError if needs args aren't specified
+		gid and perms aren't listed do to an oddity python currying mechanism
+		gid=portage_gid
+		perms=0665"""
+
+		for x,y in (("gid",portage_gid),("perms",0664)):
+			if x in config:
+				setattr(self, "_"+x, config[x])
+				del config[x]
+			else:
+				setattr(self, "_"+x, y)
+		super(FsBased, self).__init__(*args, **config)
+
+		if self.label.startswith(os.path.sep):
+			# normpath.
+			self.label = os.path.sep + os.path.normpath(self.label).lstrip(os.path.sep)
+
+
+	def _ensure_access(self, path, mtime=-1):
+		"""returns true or false if it's able to ensure that path is properly chmod'd and chowned.
+		if mtime is specified, attempts to ensure that's correct also"""
+		try:
+			os.chown(path, -1, self._gid)
+			os.chmod(path, self._perms)
+			if mtime:
+				mtime=long(mtime)
+				os.utime(path, (mtime, mtime))
+		except (OSError, IOError):
+			return False
+		return True
+
+	def _ensure_dirs(self, path=None):
+		"""with path!=None, ensure beyond self.location.  otherwise, ensure self.location"""
+		if path:
+			path = os.path.dirname(path)
+			base = self.location
+		else:
+			path = self.location
+			base='/'
+
+		for dir in path.lstrip(os.path.sep).rstrip(os.path.sep).split(os.path.sep):
+			base = os.path.join(base,dir)
+			if not os.path.exists(base):
+				um=os.umask(0)
+				try:
+					os.mkdir(base, self._perms | 0111)
+					os.chown(base, -1, self._gid)
+				finally:
+					os.umask(um)
+
+	
+def gen_label(base, label):
+	"""if supplied label is a path, generate a unique label based upon label, and supplied base path"""
+	if label.find(os.path.sep) == -1:
+		return label
+	label = label.strip("\"").strip("'")
+	label = os.path.join(*(label.rstrip(os.path.sep).split(os.path.sep)))
+	tail = os.path.split(label)[1]
+	return "%s-%X" % (tail, abs(label.__hash__()))
+
Index: /vendor/portage/current/pym/cache/mappings.py
===================================================================
--- /vendor/portage/current/pym/cache/mappings.py	(revision 3419)
+++ /vendor/portage/current/pym/cache/mappings.py	(revision 3419)
@@ -0,0 +1,103 @@
+# Copyright: 2005 Gentoo Foundation
+# Author(s): Brian Harring (ferringb@gentoo.org)
+# License: GPL2
+# $Id: mappings.py 3483 2006-06-10 21:40:40Z genone $
+
+import UserDict
+
+class ProtectedDict(UserDict.DictMixin):
+	"""
+	given an initial dict, this wraps that dict storing changes in a secondary dict, protecting
+	the underlying dict from changes
+	"""
+	__slots__=("orig","new","blacklist")
+
+	def __init__(self, orig):
+		self.orig = orig
+		self.new = {}
+		self.blacklist = {}
+
+
+	def __setitem__(self, key, val):
+		self.new[key] = val
+		if key in self.blacklist:
+			del self.blacklist[key]
+
+
+	def __getitem__(self, key):
+		if key in self.new:
+			return self.new[key]
+		if key in self.blacklist:
+			raise KeyError(key)
+		return self.orig[key]
+
+
+	def __delitem__(self, key):
+		if key in self.new:
+			del self.new[key]
+		elif key in self.orig:
+			if key not in self.blacklist:
+				self.blacklist[key] = True
+				return
+		raise KeyError(key)
+			
+
+	def __iter__(self):
+		for k in self.new.iterkeys():
+			yield k
+		for k in self.orig.iterkeys():
+			if k not in self.blacklist and k not in self.new:
+				yield k
+
+
+	def keys(self):
+		return list(self.__iter__())
+
+
+	def has_key(self, key):
+		return key in self.new or (key not in self.blacklist and key in self.orig)
+
+
+class LazyLoad(UserDict.DictMixin):
+	"""
+	Lazy loading of values for a dict
+	"""
+	__slots__=("pull", "d")
+
+	def __init__(self, pull_items_func, initial_items=[]):
+		self.d = {}
+		for k, v in initial_items:
+			self.d[k] = v
+		self.pull = pull_items_func
+
+	def __getitem__(self, key):
+		if key in self.d:
+			return self.d[key]
+		elif self.pull != None:
+			self.d.update(self.pull())
+			self.pull = None
+		return self.d[key]
+
+
+	def __iter__(self):
+		return iter(self.keys())
+
+	def keys(self):
+		if self.pull != None:
+			self.d.update(self.pull())
+			self.pull = None
+		return self.d.keys()
+
+
+	def has_key(self, key):
+		return key in self
+
+
+	def __contains__(self, key):
+		if key in self.d:
+			return True
+		elif self.pull != None:
+			self.d.update(self.pull())
+			self.pull = None
+		return key in self.d
+
Index: /vendor/portage/current/pym/cache/metadata.py
===================================================================
--- /vendor/portage/current/pym/cache/metadata.py	(revision 3419)
+++ /vendor/portage/current/pym/cache/metadata.py	(revision 3419)
@@ -0,0 +1,87 @@
+# Copyright: 2005 Gentoo Foundation
+# Author(s): Brian Harring (ferringb@gentoo.org)
+# License: GPL2
+# $Id: metadata.py 4820 2006-10-26 06:39:47Z zmedico $
+
+import os, stat, types
+from cache import flat_hash
+import eclass_cache 
+from cache.template import reconstruct_eclasses
+from cache.mappings import ProtectedDict
+
+# this is the old cache format, flat_list.  count maintained here.
+magic_line_count = 22
+
+# store the current key order *here*.
+class database(flat_hash.database):
+	complete_eclass_entries = False
+	auxdbkey_order=('DEPEND', 'RDEPEND', 'SLOT', 'SRC_URI',
+		'RESTRICT',  'HOMEPAGE',  'LICENSE', 'DESCRIPTION',
+		'KEYWORDS',  'INHERITED', 'IUSE', 'CDEPEND',
+		'PDEPEND',   'PROVIDE', 'EAPI')
+
+	autocommits = True
+
+	def __init__(self, location, *args, **config):
+		loc = location
+		super(database, self).__init__(location, *args, **config)
+		self.location = os.path.join(loc, "metadata","cache")
+		self.ec = eclass_cache.cache(loc)
+
+	def __getitem__(self, cpv):
+		return flat_hash.database.__getitem__(self, cpv)
+
+
+	def _parse_data(self, data, cpv):
+		# easy attempt first.
+		data = list(data)
+		if len(data) != magic_line_count:
+			d = flat_hash.database._parse_data(self, data, cpv)
+		else:
+			# this one's interesting.
+			d = {}
+
+			for line in data:
+				# yes, meant to iterate over a string.
+				hashed = False
+				# poor mans enumerate.  replace when python 2.3 is required
+				for idx, c in zip(range(len(line)), line):
+					if not c.isalpha():
+						if c == "=" and idx > 0:
+							hashed = True
+							d[line[:idx]] = line[idx + 1:].rstrip("\n")
+						elif c == "_" or c.isdigit():
+							continue
+						break
+
+				if not hashed:
+					# non hashed.
+					d.clear()
+					# poor mans enumerate.  replace when python 2.3 is required
+					for idx, key in zip(range(len(self.auxdbkey_order)), self.auxdbkey_order):
+						d[key] = data[idx].strip()
+					break
+
+		if "_eclasses_" not in d:
+			if "INHERITED" in d:
+				d["_eclasses_"] = self.ec.get_eclass_data(d["INHERITED"].split(), from_master_only=True)
+				del d["INHERITED"]
+		elif isinstance(d["_eclasses_"], basestring):
+			# We skip this if flat_hash.database._parse_data() was called above
+			# because it calls reconstruct_eclasses() internally.
+			d["_eclasses_"] = reconstruct_eclasses(None, d["_eclasses_"])
+
+		return d
+
+
+		
+	def _setitem(self, cpv, values):
+		values = ProtectedDict(values)
+		
+		# hack.  proper solution is to make this a __setitem__ override, since template.__setitem__ 
+		# serializes _eclasses_, then we reconstruct it.
+		if "_eclasses_" in values:
+			values["INHERITED"] = ' '.join(reconstruct_eclasses(cpv, values["_eclasses_"]).keys())
+			del values["_eclasses_"]
+
+		flat_hash.database._setitem(self, cpv, values)
Index: /vendor/portage/current/pym/cache/metadata_overlay.py
===================================================================
--- /vendor/portage/current/pym/cache/metadata_overlay.py	(revision 3419)
+++ /vendor/portage/current/pym/cache/metadata_overlay.py	(revision 3419)
@@ -0,0 +1,105 @@
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+import time
+if not hasattr(__builtins__, "set"):
+	from sets import Set as set
+from cache import template
+from cache.cache_errors import CacheCorruption
+from cache.flat_hash import database as db_rw
+from cache.metadata import database as db_ro
+
+class database(template.database):
+
+	serialize_eclasses = False
+
+	def __init__(self, location, label, auxdbkeys, db_rw=db_rw, db_ro=db_ro,
+		*args, **config):
+		super_config = config.copy()
+		super_config.pop("gid", None)
+		super(database, self).__init__(location, label, auxdbkeys,
+			*args, **super_config)
+		self.db_rw = db_rw(location, label, auxdbkeys, **config)
+		self.commit = self.db_rw.commit
+		self.autocommits = self.db_rw.autocommits
+		if isinstance(db_ro, type):
+			ro_config = config.copy()
+			ro_config["readonly"] = True
+			self.db_ro = db_ro(label, "metadata/cache", auxdbkeys, **ro_config)
+		else:
+			self.db_ro = db_ro
+
+	def __getitem__(self, cpv):
+		"""funnel whiteout validation through here, since value needs to be fetched"""
+		try:
+			value = self.db_rw[cpv]
+		except KeyError:
+			return self.db_ro[cpv] # raises a KeyError when necessary
+		except CacheCorruption:
+			del self.db_rw[cpv]
+			return self.db_ro[cpv] # raises a KeyError when necessary
+		if self._is_whiteout(value):
+			if self._is_whiteout_valid(cpv, value):
+				raise KeyError(cpv)
+			else:
+				del self.db_rw[cpv]
+				return self.db_ro[cpv] # raises a KeyError when necessary
+		else:
+			return value
+
+	def _setitem(self, name, values):
+		value_ro = self.db_ro.get(name, None)
+		if value_ro is not None and \
+			self._are_values_identical(value_ro, values):
+			# we have matching values in the underlying db_ro
+			# so it is unnecessary to store data in db_rw
+			try:
+				del self.db_rw[name] # delete unwanted whiteout when necessary
+			except KeyError:
+				pass
+			return
+		self.db_rw[name] = values
+
+	def _delitem(self, cpv):
+		value = self[cpv] # validates whiteout and/or raises a KeyError when necessary
+		if self.db_ro.has_key(cpv):
+			self.db_rw[cpv] = self._create_whiteout(value)
+		else:
+			del self.db_rw[cpv]
+
+	def __contains__(self, cpv):
+		try:
+			self[cpv] # validates whiteout when necessary
+		except KeyError:
+			return False
+		return True
+
+	def iterkeys(self):
+		s = set()
+		for cpv in self.db_rw.iterkeys():
+			if self.has_key(cpv): # validates whiteout when necessary
+				yield cpv
+			# set includes whiteouts so they won't be yielded later
+			s.add(cpv)
+		for cpv in self.db_ro.iterkeys():
+			if cpv not in s:
+				yield cpv
+
+	def _is_whiteout(self, value):
+		return value["EAPI"] == "whiteout"
+
+	def _create_whiteout(self, value):
+		return {"EAPI":"whiteout","_eclasses_":value["_eclasses_"],"_mtime_":value["_mtime_"]}
+
+	def _is_whiteout_valid(self, name, value_rw):
+		try:
+			value_ro = self.db_ro[name]
+			return self._are_values_identical(value_rw,value_ro)
+		except KeyError:
+			return False
+
+	def _are_values_identical(self, value1, value2):
+		if long(value1["_mtime_"]) != long(value2["_mtime_"]):
+			return False
+		return value1["_eclasses_"] == value2["_eclasses_"]
Index: /vendor/portage/current/pym/cache/sql_template.py
===================================================================
--- /vendor/portage/current/pym/cache/sql_template.py	(revision 3419)
+++ /vendor/portage/current/pym/cache/sql_template.py	(revision 3419)
@@ -0,0 +1,275 @@
+# Copyright: 2005 Gentoo Foundation
+# Author(s): Brian Harring (ferringb@gentoo.org)
+# License: GPL2
+# $Id: sql_template.py 4821 2006-10-26 08:10:35Z zmedico $
+
+from cache import template, cache_errors
+from cache.template import reconstruct_eclasses
+
+class SQLDatabase(template.database):
+	"""template class for RDBM based caches
+	
+	This class is designed such that derivatives don't have to change much code, mostly constant strings.
+	_BaseError must be an exception class that all Exceptions thrown from the derived RDBMS are derived
+	from.
+
+	SCHEMA_INSERT_CPV_INTO_PACKAGE should be modified dependant on the RDBMS, as should SCHEMA_PACKAGE_CREATE-
+	basically you need to deal with creation of a unique pkgid.  If the dbapi2 rdbms class has a method of 
+	recovering that id, then modify _insert_cpv to remove the extra select.
+
+	Creation of a derived class involves supplying _initdb_con, and table_exists.
+	Additionally, the default schemas may have to be modified.
+	"""
+	
+	SCHEMA_PACKAGE_NAME	= "package_cache"
+	SCHEMA_PACKAGE_CREATE 	= "CREATE TABLE %s (\
+		pkgid INTEGER PRIMARY KEY, label VARCHAR(255), cpv VARCHAR(255), UNIQUE(label, cpv))" % SCHEMA_PACKAGE_NAME
+	SCHEMA_PACKAGE_DROP	= "DROP TABLE %s" % SCHEMA_PACKAGE_NAME
+
+	SCHEMA_VALUES_NAME	= "values_cache"
+	SCHEMA_VALUES_CREATE	= "CREATE TABLE %s ( pkgid integer references %s (pkgid) on delete cascade, \
+		key varchar(255), value text, UNIQUE(pkgid, key))" % (SCHEMA_VALUES_NAME, SCHEMA_PACKAGE_NAME)
+	SCHEMA_VALUES_DROP	= "DROP TABLE %s" % SCHEMA_VALUES_NAME
+	SCHEMA_INSERT_CPV_INTO_PACKAGE	= "INSERT INTO %s (label, cpv) VALUES(%%s, %%s)" % SCHEMA_PACKAGE_NAME
+
+	_BaseError = ()
+	_dbClass = None
+
+	autocommits = False
+#	cleanse_keys = True
+
+	# boolean indicating if the derived RDBMS class supports replace syntax
+	_supports_replace = False
+
+	def __init__(self, location, label, auxdbkeys, *args, **config):
+		"""initialize the instance.
+		derived classes shouldn't need to override this"""
+
+		super(SQLDatabase, self).__init__(location, label, auxdbkeys, *args, **config)
+
+		config.setdefault("host","127.0.0.1")
+		config.setdefault("autocommit", self.autocommits)
+		self._initdb_con(config)
+
+		self.label = self._sfilter(self.label)
+
+
+	def _dbconnect(self, config):
+		"""should be overridden if the derived class needs special parameters for initializing
+		the db connection, or cursor"""
+		self.db = self._dbClass(**config)
+		self.con = self.db.cursor()
+
+
+	def _initdb_con(self,config):
+		"""ensure needed tables are in place.
+		If the derived class needs a different set of table creation commands, overload the approriate
+		SCHEMA_ attributes.  If it needs additional execution beyond, override"""
+
+		self._dbconnect(config)
+		if not self._table_exists(self.SCHEMA_PACKAGE_NAME):
+			if self.readonly:
+				raise cache_errors.ReadOnlyRestriction("table %s doesn't exist" % \
+					self.SCHEMA_PACKAGE_NAME)
+			try:	self.con.execute(self.SCHEMA_PACKAGE_CREATE)
+			except  self._BaseError, e:
+				raise cache_errors.InitializationError(self.__class__, e)
+
+		if not self._table_exists(self.SCHEMA_VALUES_NAME):
+			if self.readonly:
+				raise cache_errors.ReadOnlyRestriction("table %s doesn't exist" % \
+					self.SCHEMA_VALUES_NAME)
+			try:	self.con.execute(self.SCHEMA_VALUES_CREATE)
+			except	self._BaseError, e:
+				raise cache_errors.InitializationError(self.__class__, e)
+
+
+	def _table_exists(self, tbl):
+		"""return true if a table exists
+		derived classes must override this"""
+		raise NotImplementedError
+
+
+	def _sfilter(self, s):
+		"""meta escaping, returns quoted string for use in sql statements"""
+		return "\"%s\"" % s.replace("\\","\\\\").replace("\"","\\\"")
+
+
+	def _getitem(self, cpv):
+		try:	self.con.execute("SELECT key, value FROM %s NATURAL JOIN %s "
+			"WHERE label=%s AND cpv=%s" % (self.SCHEMA_PACKAGE_NAME, self.SCHEMA_VALUES_NAME,
+			self.label, self._sfilter(cpv)))
+		except self._BaseError, e:
+			raise cache_errors.CacheCorruption(self, cpv, e)
+
+		rows = self.con.fetchall()
+
+		if len(rows) == 0:
+			raise KeyError(cpv)
+
+		vals = dict([(k,"") for k in self._known_keys])
+		vals.update(dict(rows))
+		return vals
+
+
+	def _delitem(self, cpv):
+		"""delete a cpv cache entry
+		derived RDBM classes for this *must* either support cascaded deletes, or 
+		override this method"""
+		try:
+			try:	
+				self.con.execute("DELETE FROM %s WHERE label=%s AND cpv=%s" % \
+				(self.SCHEMA_PACKAGE_NAME, self.label, self._sfilter(cpv)))
+				if self.autocommits:
+					self.commit()
+			except self._BaseError, e:
+				raise cache_errors.CacheCorruption(self, cpv, e)
+			if self.con.rowcount <= 0:
+				raise KeyError(cpv)
+		except Exception:
+			if not self.autocommits:
+				self.db.rollback()
+				# yes, this can roll back a lot more then just the delete.  deal.
+			raise
+
+	def __del__(self):
+		# just to be safe.
+		if "db" in self.__dict__ and self.db != None:
+			self.commit()
+			self.db.close()
+
+	def _setitem(self, cpv, values):
+
+		try:
+			# insert.
+			try:	pkgid = self._insert_cpv(cpv)
+			except self._BaseError, e:
+				raise cache_errors.CacheCorruption(cpv, e)
+
+			# __getitem__ fills out missing values, 
+			# so we store only what's handed to us and is a known key
+			db_values = []
+			for key in self._known_keys:
+				if values.has_key(key) and values[key] != '':
+					db_values.append({"key":key, "value":values[key]})
+
+			if len(db_values) > 0:
+				try:	self.con.executemany("INSERT INTO %s (pkgid, key, value) VALUES(\"%s\", %%(key)s, %%(value)s)" % \
+					(self.SCHEMA_VALUES_NAME, str(pkgid)), db_values)
+				except self._BaseError, e:
+					raise cache_errors.CacheCorruption(cpv, e)
+			if self.autocommits:
+				self.commit()
+
+		except Exception:
+			if not self.autocommits:
+				try:	self.db.rollback()
+				except self._BaseError: pass
+			raise
+
+
+	def _insert_cpv(self, cpv):
+		"""uses SCHEMA_INSERT_CPV_INTO_PACKAGE, which must be overloaded if the table definition
+		doesn't support auto-increment columns for pkgid.
+		returns the cpvs new pkgid
+		note this doesn't commit the transaction.  The caller is expected to."""
+		
+		cpv = self._sfilter(cpv)
+		if self._supports_replace:
+			query_str = self.SCHEMA_INSERT_CPV_INTO_PACKAGE.replace("INSERT","REPLACE",1)
+		else:
+			# just delete it.
+			try:	del self[cpv]
+			except	(cache_errors.CacheCorruption, KeyError):	pass
+			query_str = self.SCHEMA_INSERT_CPV_INTO_PACKAGE
+		try:
+			self.con.execute(query_str % (self.label, cpv))
+		except self._BaseError:
+			self.db.rollback()
+			raise
+		self.con.execute("SELECT pkgid FROM %s WHERE label=%s AND cpv=%s" % \
+			(self.SCHEMA_PACKAGE_NAME, self.label, cpv))
+			
+		if self.con.rowcount != 1:
+			raise cache_error.CacheCorruption(cpv, "Tried to insert the cpv, but found "
+				" %i matches upon the following select!" % len(rows))
+		return self.con.fetchone()[0]
+
+
+	def __contains__(self, cpv):
+		if not self.autocommits:
+			try:	self.commit()
+			except self._BaseError, e:
+				raise cache_errors.GeneralCacheCorruption(e)
+
+		try:	self.con.execute("SELECT cpv FROM %s WHERE label=%s AND cpv=%s" % \
+				(self.SCHEMA_PACKAGE_NAME, self.label, self._sfilter(cpv)))
+		except self._BaseError, e:
+			raise cache_errors.GeneralCacheCorruption(e)
+		return self.con.rowcount > 0
+
+
+	def iterkeys(self):
+		if not self.autocommits:
+			try:	self.commit()
+			except self._BaseError, e:
+				raise cache_errors.GeneralCacheCorruption(e)
+
+		try:	self.con.execute("SELECT cpv FROM %s WHERE label=%s" % 
+				(self.SCHEMA_PACKAGE_NAME, self.label))
+		except self._BaseError, e:
+			raise cache_errors.GeneralCacheCorruption(e)
+#		return [ row[0] for row in self.con.fetchall() ]
+		for x in self.con.fetchall():
+			yield x[0]
+
+	def iteritems(self):
+		try:	self.con.execute("SELECT cpv, key, value FROM %s NATURAL JOIN %s "
+			"WHERE label=%s" % (self.SCHEMA_PACKAGE_NAME, self.SCHEMA_VALUES_NAME,
+			self.label))
+		except self._BaseError, e:
+			raise cache_errors.CacheCorruption(self, cpv, e)
+		
+		oldcpv = None
+		l = []
+		for x, y, v in self.con.fetchall():
+			if oldcpv != x:
+				if oldcpv != None:
+					d = dict(l)
+					if "_eclasses_" in d:
+						d["_eclasses_"] = reconstruct_eclasses(oldcpv, d["_eclasses_"])
+					yield cpv, d
+				l.clear()
+				oldcpv = x
+			l.append((y,v))
+		if oldcpv != None:
+			d = dict(l)
+			if "_eclasses_" in d:
+				d["_eclasses_"] = reconstruct_eclasses(oldcpv, d["_eclasses_"])
+			yield cpv, d			
+
+	def commit(self):
+		self.db.commit()
+
+	def get_matches(self,match_dict):
+		query_list = []
+		for k,v in match_dict.items():
+			if k not in self._known_keys:
+				raise cache_errors.InvalidRestriction(k, v, "key isn't known to this cache instance")
+			v = v.replace("%","\\%")
+			v = v.replace(".*","%")
+			query_list.append("(key=%s AND value LIKE %s)" % (self._sfilter(k), self._sfilter(v)))
+
+		if len(query_list):
+			query = " AND "+" AND ".join(query_list)
+		else:
+			query = ''
+
+		print "query = SELECT cpv from package_cache natural join values_cache WHERE label=%s %s" % (self.label, query)
+		try:	self.con.execute("SELECT cpv from package_cache natural join values_cache WHERE label=%s %s" % \
+				(self.label, query))
+		except self._BaseError, e:
+			raise cache_errors.GeneralCacheCorruption(e)
+
+		return [ row[0] for row in self.con.fetchall() ]
+
Index: /vendor/portage/current/pym/cache/sqlite.py
===================================================================
--- /vendor/portage/current/pym/cache/sqlite.py	(revision 3419)
+++ /vendor/portage/current/pym/cache/sqlite.py	(revision 3419)
@@ -0,0 +1,236 @@
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+from cache import fs_template
+from cache import cache_errors
+import os
+from cache.template import reconstruct_eclasses
+from portage_util import writemsg, apply_secpass_permissions
+from portage_data import portage_gid
+try:
+	import sqlite3 as db_module # sqlite3 is optional with >=python-2.5
+except ImportError:
+	from pysqlite2 import dbapi2 as db_module
+DBError = db_module.Error
+
+class database(fs_template.FsBased):
+
+	autocommits = False
+	synchronous = False
+	# cache_bytes is used together with page_size (set at sqlite build time)
+	# to calculate the number of pages requested, according to the following
+	# equation: cache_bytes = page_bytes * page_count
+	cache_bytes = 1024 * 1024 * 10
+	_db_module = db_module
+	_db_error = DBError
+	_db_table = None
+
+	def __init__(self, *args, **config):
+		super(database, self).__init__(*args, **config)
+		self._allowed_keys = ["_mtime_", "_eclasses_"] + self._known_keys
+		self.location = os.path.join(self.location, 
+			self.label.lstrip(os.path.sep).rstrip(os.path.sep))
+
+		if not os.path.exists(self.location):
+			self._ensure_dirs()
+
+		config.setdefault("autocommit", self.autocommits)
+		config.setdefault("cache_bytes", self.cache_bytes)
+		config.setdefault("synchronous", self.synchronous)
+		# Timeout for throwing a "database is locked" exception (pysqlite
+		# default is 5.0 seconds).
+		config.setdefault("timeout", 15)
+		self._db_init_connection(config)
+		self._db_init_structures()
+
+	def _db_escape_string(self, s):
+		"""meta escaping, returns quoted string for use in sql statements"""
+		return "'%s'" % str(s).replace("\\","\\\\").replace("'","''")
+
+	def _db_init_connection(self, config):
+		self._dbpath = self.location + ".sqlite"
+		#if os.path.exists(self._dbpath):
+		#	os.unlink(self._dbpath)
+		connection_kwargs = {}
+		connection_kwargs["timeout"] = config["timeout"]
+		try:
+			self._ensure_dirs()
+			self._db_connection = self._db_module.connect(
+				database=self._dbpath, **connection_kwargs)
+			self._db_cursor = self._db_connection.cursor()
+			self._db_cursor.execute("PRAGMA encoding = %s" % self._db_escape_string("UTF-8"))
+			if not apply_secpass_permissions(self._dbpath, gid=portage_gid, mode=070, mask=02):
+				raise cache_errors.InitializationError(self.__class__, "can't ensure perms on %s" % self._dbpath)
+			self._db_init_cache_size(config["cache_bytes"])
+			self._db_init_synchronous(config["synchronous"])
+		except self._db_error, e:
+			raise cache_errors.InitializationError(self.__class__, e)
+
+	def _db_init_structures(self):
+		self._db_table = {}
+		self._db_table["packages"] = {}
+		mytable = "portage_packages"
+		self._db_table["packages"]["table_name"] = mytable
+		self._db_table["packages"]["package_id"] = "internal_db_package_id"
+		self._db_table["packages"]["package_key"] = "portage_package_key"
+		self._db_table["packages"]["internal_columns"] = \
+			[self._db_table["packages"]["package_id"],
+			self._db_table["packages"]["package_key"]]
+		create_statement = []
+		create_statement.append("CREATE TABLE")
+		create_statement.append(mytable)
+		create_statement.append("(")
+		table_parameters = []
+		table_parameters.append("%s INTEGER PRIMARY KEY AUTOINCREMENT" % self._db_table["packages"]["package_id"])
+		table_parameters.append("%s TEXT" % self._db_table["packages"]["package_key"])
+		for k in self._allowed_keys:
+			table_parameters.append("%s TEXT" % k)
+		table_parameters.append("UNIQUE(%s)" % self._db_table["packages"]["package_key"])
+		create_statement.append(",".join(table_parameters))
+		create_statement.append(")")
+		
+		self._db_table["packages"]["create"] = " ".join(create_statement)
+		self._db_table["packages"]["columns"] = \
+			self._db_table["packages"]["internal_columns"] + \
+			self._allowed_keys
+
+		cursor = self._db_cursor
+		for k, v in self._db_table.iteritems():
+			if self._db_table_exists(v["table_name"]):
+				create_statement = self._db_table_get_create(v["table_name"])
+				if create_statement != v["create"]:
+					writemsg("sqlite: dropping old table: %s\n" % v["table_name"])
+					cursor.execute("DROP TABLE %s" % v["table_name"])
+					cursor.execute(v["create"])
+			else:
+				cursor.execute(v["create"])
+
+	def _db_table_exists(self, table_name):
+		"""return true/false dependant on a tbl existing"""
+		cursor = self._db_cursor
+		cursor.execute("SELECT name FROM sqlite_master WHERE type=\"table\" AND name=%s" % \
+			self._db_escape_string(table_name))
+		return len(cursor.fetchall()) == 1
+
+	def _db_table_get_create(self, table_name):
+		"""return true/false dependant on a tbl existing"""
+		cursor = self._db_cursor
+		cursor.execute("SELECT sql FROM sqlite_master WHERE name=%s" % \
+			self._db_escape_string(table_name))
+		return cursor.fetchall()[0][0]
+
+	def _db_init_cache_size(self, cache_bytes):
+		cursor = self._db_cursor
+		cursor.execute("PRAGMA page_size")
+		page_size=int(cursor.fetchone()[0])
+		# number of pages, sqlite default is 2000
+		cache_size = cache_bytes / page_size
+		cursor.execute("PRAGMA cache_size = %d" % cache_size)
+		cursor.execute("PRAGMA cache_size")
+		actual_cache_size = int(cursor.fetchone()[0])
+		del cursor
+		if actual_cache_size != cache_size:
+			raise cache_errors.InitializationError(self.__class__,"actual cache_size = "+actual_cache_size+" does does not match requested size of "+cache_size)
+
+	def _db_init_synchronous(self, synchronous):
+		cursor = self._db_cursor
+		cursor.execute("PRAGMA synchronous = %d" % synchronous)
+		cursor.execute("PRAGMA synchronous")
+		actual_synchronous=int(cursor.fetchone()[0])
+		del cursor
+		if actual_synchronous!=synchronous:
+			raise cache_errors.InitializationError(self.__class__,"actual synchronous = "+actual_synchronous+" does does not match requested value of "+synchronous)
+
+	def __getitem__(self, cpv):
+		cursor = self._db_cursor
+		cursor.execute("select * from %s where %s=%s" % \
+			(self._db_table["packages"]["table_name"],
+			self._db_table["packages"]["package_key"],
+			self._db_escape_string(cpv)))
+		result = cursor.fetchall()
+		if len(result) == 1:
+			pass
+		elif len(result) == 0:
+			raise KeyError(cpv)
+		else:
+			raise cache_errors.CacheCorruption(cpv, "key is not unique")
+		d = {}
+		internal_columns = self._db_table["packages"]["internal_columns"]
+		column_index = -1
+		for k in self._db_table["packages"]["columns"]:
+			column_index +=1
+			if k not in internal_columns:
+				d[k] = result[0][column_index]
+		# XXX: The resolver chokes on unicode strings so we convert them here.
+		for k in d.keys():
+			try:
+				d[k]=str(d[k]) # convert unicode strings to normal
+			except UnicodeEncodeError, e:
+				pass #writemsg("%s: %s\n" % (cpv, str(e)))
+		if "_eclasses_" in d:
+			d["_eclasses_"] = reconstruct_eclasses(cpv, d["_eclasses_"])
+		for x in self._known_keys:
+			d.setdefault(x,'')
+		return d
+
+	def _setitem(self, cpv, values):
+		update_statement = []
+		update_statement.append("REPLACE INTO %s" % self._db_table["packages"]["table_name"])
+		update_statement.append("(")
+		update_statement.append(','.join([self._db_table["packages"]["package_key"]] + self._allowed_keys))
+		update_statement.append(")")
+		update_statement.append("VALUES")
+		update_statement.append("(")
+		values_parameters = []
+		values_parameters.append(self._db_escape_string(cpv))
+		for k in self._allowed_keys:
+			values_parameters.append(self._db_escape_string(values.get(k, '')))
+		update_statement.append(",".join(values_parameters))
+		update_statement.append(")")
+		cursor = self._db_cursor
+		try:
+			s = " ".join(update_statement)
+			cursor.execute(s)
+		except self._db_error, e:
+			writemsg("%s: %s\n" % (cpv, str(e)))
+			raise
+
+	def commit(self):
+		self._db_connection.commit()
+
+	def _delitem(self, cpv):
+		cursor = self._db_cursor
+		cursor.execute("DELETE FROM %s WHERE %s=%s" % \
+			(self._db_table["packages"]["table_name"],
+			self._db_table["packages"]["package_key"],
+			self._db_escape_string(cpv)))
+
+	def __contains__(self, cpv):
+		cursor = self._db_cursor
+		cursor.execute(" ".join(
+			["SELECT %s FROM %s" %
+			(self._db_table["packages"]["package_id"],
+			self._db_table["packages"]["table_name"]),
+			"WHERE %s=%s" % (
+			self._db_table["packages"]["package_key"],
+			self._db_escape_string(cpv))]))
+		result = cursor.fetchall()
+		if len(result) == 0:
+			return False
+		elif len(result) == 1:
+			return True
+		else:
+			raise cache_errors.CacheCorruption(cpv, "key is not unique")
+
+	def iterkeys(self):
+		"""generator for walking the dir struct"""
+		cursor = self._db_cursor
+		cursor.execute("SELECT %s FROM %s" % \
+			(self._db_table["packages"]["package_key"],
+			self._db_table["packages"]["table_name"]))
+		result = cursor.fetchall()
+		key_list = [x[0] for x in result]
+		del result
+		while key_list:
+			yield key_list.pop()
Index: /vendor/portage/current/pym/cache/template.py
===================================================================
--- /vendor/portage/current/pym/cache/template.py	(revision 3419)
+++ /vendor/portage/current/pym/cache/template.py	(revision 3419)
@@ -0,0 +1,200 @@
+# Copyright: 2005 Gentoo Foundation
+# Author(s): Brian Harring (ferringb@gentoo.org)
+# License: GPL2
+# $Id: template.py 4855 2006-10-27 21:45:29Z zmedico $
+
+from cache import cache_errors
+from cache.cache_errors import InvalidRestriction
+from cache.mappings import ProtectedDict
+
+class database(object):
+	# this is for metadata/cache transfer.
+	# basically flags the cache needs be updated when transfered cache to cache.
+	# leave this.
+
+	complete_eclass_entries = True
+	autocommits = False
+	cleanse_keys = False
+	serialize_eclasses = True
+
+	def __init__(self, location, label, auxdbkeys, readonly=False):
+		""" initialize the derived class; specifically, store label/keys"""
+		self._known_keys = auxdbkeys
+		self.location = location
+		self.label = label
+		self.readonly = readonly
+		self.sync_rate = 0
+		self.updates = 0
+	
+	def __getitem__(self, cpv):
+		"""set a cpv to values
+		This shouldn't be overriden in derived classes since it handles the __eclasses__ conversion.
+		that said, if the class handles it, they can override it."""
+		if self.updates > self.sync_rate:
+			self.commit()
+			self.updates = 0
+		d=self._getitem(cpv)
+		if self.serialize_eclasses and "_eclasses_" in d:
+			d["_eclasses_"] = reconstruct_eclasses(cpv, d["_eclasses_"])
+		return d
+
+	def _getitem(self, cpv):
+		"""get cpv's values.
+		override this in derived classess"""
+		raise NotImplementedError
+
+	def __setitem__(self, cpv, values):
+		"""set a cpv to values
+		This shouldn't be overriden in derived classes since it handles the readonly checks"""
+		if self.readonly:
+			raise cache_errors.ReadOnlyRestriction()
+		if self.cleanse_keys:
+			d=ProtectedDict(values)
+			for k in d.keys():
+				if d[k] == '':
+					del d[k]
+			if self.serialize_eclasses and "_eclasses_" in values:
+				d["_eclasses_"] = serialize_eclasses(d["_eclasses_"])
+		elif self.serialize_eclasses and "_eclasses_" in values:
+			d = ProtectedDict(values)
+			d["_eclasses_"] = serialize_eclasses(d["_eclasses_"])
+		else:
+			d = values
+		self._setitem(cpv, d)
+		if not self.autocommits:
+			self.updates += 1
+			if self.updates > self.sync_rate:
+				self.commit()
+				self.updates = 0
+
+	def _setitem(self, name, values):
+		"""__setitem__ calls this after readonly checks.  override it in derived classes
+		note _eclassees_ key *must* be handled"""
+		raise NotImplementedError
+
+	def __delitem__(self, cpv):
+		"""delete a key from the cache.
+		This shouldn't be overriden in derived classes since it handles the readonly checks"""
+		if self.readonly:
+			raise cache_errors.ReadOnlyRestriction()
+		if not self.autocommits:
+			self.updates += 1
+		self._delitem(cpv)
+		if self.updates > self.sync_rate:
+			self.commit()
+			self.updates = 0
+
+	def _delitem(self,cpv):
+		"""__delitem__ calls this after readonly checks.  override it in derived classes"""
+		raise NotImplementedError
+
+	def has_key(self, cpv):
+		return cpv in self
+
+	def keys(self):
+		return tuple(self.iterkeys())
+
+	def iterkeys(self):
+		raise NotImplementedError
+
+	def iteritems(self):
+		for x in self.iterkeys():
+			yield (x, self[x])
+
+	def items(self):
+		return list(self.iteritems())
+
+	def sync(self, rate=0):
+		self.sync_rate = rate
+		if(rate == 0):
+			self.commit()
+
+	def commit(self):
+		if not self.autocommits:
+			raise NotImplementedError
+
+	def __contains__(self, cpv):
+		"""This method should always be overridden.  It is provided only for
+		backward compatibility with modules that override has_key instead.  It
+		will automatically raise a NotImplementedError if has_key has not been
+		overridden."""
+		if self.has_key is database.has_key:
+			# prevent a possible recursive loop
+			raise NotImplementedError
+		return self.has_key(cpv)
+
+	def get(self, k, x=None):
+		try:
+			return self[k]
+		except KeyError:
+			return x
+
+	def get_matches(self, match_dict):
+		"""generic function for walking the entire cache db, matching restrictions to
+		filter what cpv's are returned.  Derived classes should override this if they
+		can implement a faster method then pulling each cpv:values, and checking it.
+		
+		For example, RDBMS derived classes should push the matching logic down to the
+		actual RDBM."""
+
+		import re
+		restricts = {}
+		for key,match in match_dict.iteritems():
+			# XXX this sucks.
+			try:
+				if isinstance(match, str):
+					restricts[key] = re.compile(match).match
+				else:
+					restricts[key] = re.compile(match[0],match[1]).match
+			except re.error, e:
+				raise InvalidRestriction(key, match, e)
+			if key not in self.__known_keys:
+				raise InvalidRestriction(key, match, "Key isn't valid")
+
+		for cpv in self.keys():
+			cont = True
+			vals = self[cpv]
+			for key, match in restricts.iteritems():
+				if not match(vals[key]):
+					cont = False
+					break
+			if cont:
+				yield cpv
+
+
+def serialize_eclasses(eclass_dict):
+	"""takes a dict, returns a string representing said dict"""
+	"""The "new format", which causes older versions of <portage-2.1.2 to
+	traceback with a ValueError due to failed long() conversion.  This format
+	isn't currently written, but the the capability to read it is already built
+	in.
+	return "\t".join(["%s\t%s" % (k, str(v)) \
+		for k, v in eclass_dict.iteritems()])
+	"""
+	if not eclass_dict:
+		return ""
+	return "\t".join(["%s\t%s\t%s" % (k, v[0], str(v[1])) \
+		for k, v in eclass_dict.iteritems()])
+
+def reconstruct_eclasses(cpv, eclass_string):
+	"""returns a dict when handed a string generated by serialize_eclasses"""
+	eclasses = eclass_string.rstrip().lstrip().split("\t")
+	if eclasses == [""]:
+		# occasionally this occurs in the fs backends.  they suck.
+		return {}
+	
+	if len(eclasses) % 2 != 0 and len(eclasses) % 3 != 0:
+		raise cache_errors.CacheCorruption(cpv, "_eclasses_ was of invalid len %i" % len(eclasses))
+	d={}
+	try:
+		if eclasses[1].isdigit():
+			for x in xrange(0, len(eclasses), 2):
+				d[eclasses[x]] = ("", long(eclasses[x + 1]))
+		else:
+			# The old format contains paths that will be discarded.
+			for x in xrange(0, len(eclasses), 3):
+				d[eclasses[x]] = (eclasses[x + 1], long(eclasses[x + 2]))
+	except ValueError:
+		raise cache_errors.CacheCorruption(cpv, "_eclasses_ mtime conversion to long failed")
+	del eclasses
+	return d
Index: /vendor/portage/current/pym/cache/util.py
===================================================================
--- /vendor/portage/current/pym/cache/util.py	(revision 3419)
+++ /vendor/portage/current/pym/cache/util.py	(revision 3419)
@@ -0,0 +1,131 @@
+# Copyright: 2005 Gentoo Foundation
+# Author(s): Brian Harring (ferringb@gentoo.org)
+# License: GPL2
+# $Id: util.py 5483 2007-01-08 16:20:31Z zmedico $
+
+if not hasattr(__builtins__, "set"):
+	from sets import Set as set
+from itertools import chain
+from cache import cache_errors
+
+def mirror_cache(valid_nodes_iterable, src_cache, trg_cache, eclass_cache=None, verbose_instance=None):
+
+	if not src_cache.complete_eclass_entries and not eclass_cache:
+		raise Exception("eclass_cache required for cache's of class %s!" % src_cache.__class__)
+
+	if verbose_instance == None:
+		noise=quiet_mirroring()
+	else:
+		noise=verbose_instance
+
+	dead_nodes = {}
+	dead_nodes = dict.fromkeys(trg_cache.keys())
+	count=0
+
+	if not trg_cache.autocommits:
+		trg_cache.sync(100)
+
+	for x in valid_nodes_iterable:
+#		print "processing x=",x
+		count+=1
+		if dead_nodes.has_key(x):
+			del dead_nodes[x]
+		try:	entry = src_cache[x]
+		except KeyError, e:
+			noise.missing_entry(x)
+			del e
+			continue
+		write_it = True
+		trg = None
+		try:
+			trg = trg_cache[x]
+			if long(trg["_mtime_"]) == long(entry["_mtime_"]) and \
+				eclass_cache.is_eclass_data_valid(trg["_eclasses_"]) and \
+				set(trg["_eclasses_"]) == set(entry["_eclasses_"]):
+				write_it = False
+		except (cache_errors.CacheError, KeyError):
+			pass
+
+		if trg and not write_it:
+			""" We don't want to skip the write unless we're really sure that
+			the existing cache is identical, so don't trust _mtime_ and
+			_eclasses_ alone."""
+			for d in (entry, trg):
+				if "EAPI" in d and d["EAPI"] in ("", "0"):
+					del d["EAPI"]
+			for k in set(chain(entry, trg)).difference(
+				("_mtime_", "_eclasses_")):
+				if trg.get(k, "") != entry.get(k, ""):
+					write_it = True
+					break
+
+		if write_it:
+			try:
+				inherited = entry.get("INHERITED", None)
+			except cache_errors.CacheError, ce:
+				noise.exception(x, ce)
+				del ce
+				continue
+			if inherited:
+				if src_cache.complete_eclass_entries:
+					if not "_eclasses_" in entry:
+						noise.corruption(x,"missing _eclasses_ field")
+						continue
+					if not eclass_cache.is_eclass_data_valid(entry["_eclasses_"]):
+						noise.eclass_stale(x)
+						continue
+				else:
+					entry["_eclasses_"] = eclass_cache.get_eclass_data(entry["INHERITED"].split(), \
+						from_master_only=True)
+					if not entry["_eclasses_"]:
+						noise.eclass_stale(x)
+						continue
+
+			# by this time, if it reaches here, the eclass has been validated, and the entry has 
+			# been updated/translated (if needs be, for metadata/cache mainly)
+			try:	trg_cache[x] = entry
+			except cache_errors.CacheError, ce:
+				noise.exception(x, ce)
+				del ce
+				continue
+		if count >= noise.call_update_min:
+			noise.update(x)
+			count = 0
+
+	if not trg_cache.autocommits:
+		trg_cache.commit()
+
+	# ok.  by this time, the trg_cache is up to date, and we have a dict
+	# with a crapload of cpv's.  we now walk the target db, removing stuff if it's in the list.
+	for key in dead_nodes:
+		try:
+			del trg_cache[key]
+		except KeyError:
+			pass
+		except cache_errors.CacheError, ce:
+			noise.exception(ce)
+			del ce
+	dead_nodes.clear()
+	noise.finish()
+
+
+class quiet_mirroring(object):
+	# call_update_every is used by mirror_cache to determine how often to call in.
+	# quiet defaults to 2^24 -1.  Don't call update, 'cept once every 16 million or so :)
+	call_update_min = 0xffffff
+	def update(self,key,*arg):		pass
+	def exception(self,key,*arg):	pass
+	def eclass_stale(self,*arg):	pass
+	def missing_entry(self, key):	pass
+	def misc(self,key,*arg):		pass
+	def corruption(self, key, s):	pass
+	def finish(self, *arg):			pass
+	
+class non_quiet_mirroring(quiet_mirroring):
+	call_update_min=1
+	def update(self,key,*arg):	print "processed",key
+	def exception(self, key, *arg):	print "exec",key,arg
+	def missing(self,key):		print "key %s is missing", key
+	def corruption(self,key,*arg):	print "corrupt %s:" % key,arg
+	def eclass_stale(self,key,*arg):print "stale %s:"%key,arg
+
Index: /vendor/portage/current/pym/cache/volatile.py
===================================================================
--- /vendor/portage/current/pym/cache/volatile.py	(revision 3419)
+++ /vendor/portage/current/pym/cache/volatile.py	(revision 3419)
@@ -0,0 +1,27 @@
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+import copy
+if not hasattr(__builtins__, "set"):
+	from sets import Set as set
+from cache import template
+
+class database(template.database):
+
+	autocommits = True
+	serialize_eclasses = False
+
+	def __init__(self, *args, **config):
+		config.pop("gid", None)
+		super(database, self).__init__(*args, **config)
+		self._data = {}
+		self.iterkeys = self._data.iterkeys
+		self._delitem = self._data.__delitem__
+		self.__contains__ = self._data.__contains__
+
+	def _setitem(self, name, values):
+		self._data[name] = copy.deepcopy(values)
+
+	def _getitem(self, cpv):
+		return copy.deepcopy(self._data[cpv])
Index: /vendor/portage/current/pym/cvstree.py
===================================================================
--- /vendor/portage/current/pym/cvstree.py	(revision 3419)
+++ /vendor/portage/current/pym/cvstree.py	(revision 3419)
@@ -0,0 +1,295 @@
+# cvstree.py -- cvs tree utilities
+# Copyright 1998-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: cvstree.py 5594 2007-01-12 07:58:39Z antarus $
+
+
+import os,time,sys,re
+from stat import *
+
+# [D]/Name/Version/Date/Flags/Tags
+
+def pathdata(entries, path):
+	"""(entries,path)
+	Returns the data(dict) for a specific file/dir at the path specified."""
+	mysplit=path.split("/")
+	myentries=entries
+	mytarget=mysplit[-1]
+	mysplit=mysplit[:-1]
+	for mys in mysplit:
+		if myentries["dirs"].has_key(mys):
+			myentries=myentries["dirs"][mys]
+		else:
+			return None
+	if myentries["dirs"].has_key(mytarget):
+		return myentries["dirs"][mytarget]
+	elif myentries["files"].has_key(mytarget):
+		return myentries["files"][mytarget]
+	else:
+		return None
+
+def fileat(entries, path):
+	return pathdata(entries,path)
+
+def isadded(entries, path):
+	"""(entries,path)
+	Returns true if the path exists and is added to the cvs tree."""
+	mytarget=pathdata(entries, path)
+	if mytarget:
+		if "cvs" in mytarget["status"]:
+			return 1
+
+	basedir=os.path.dirname(path)
+	filename=os.path.basename(path)
+
+	try:
+		myfile=open(basedir+"/CVS/Entries","r")
+	except IOError:
+		return 0
+	mylines=myfile.readlines()
+	myfile.close()
+
+	rep=re.compile("^\/"+re.escape(filename)+"\/");
+	for x in mylines:
+		if rep.search(x):
+			return 1
+
+	return 0
+
+def findnew(entries,recursive=0,basedir=""):
+	"""(entries,recursive=0,basedir="")
+	Recurses the entries tree to find all elements that have been added but
+	have not yet been committed. Returns a list of paths, optionally prepended
+	with a basedir."""
+	if basedir and basedir[-1]!="/":
+		basedir=basedir+"/"
+	mylist=[]
+	for myfile in entries["files"].keys():
+		if "cvs" in entries["files"][myfile]["status"]:
+			if "0" == entries["files"][myfile]["revision"]:
+				mylist.append(basedir+myfile)
+	if recursive:
+		for mydir in entries["dirs"].keys():
+			mylist+=findnew(entries["dirs"][mydir],recursive,basedir+mydir)
+	return mylist
+					
+def findchanged(entries,recursive=0,basedir=""):
+	"""(entries,recursive=0,basedir="")
+	Recurses the entries tree to find all elements that exist in the cvs tree
+	and differ from the committed version. Returns a list of paths, optionally
+	prepended with a basedir."""
+	if basedir and basedir[-1]!="/":
+		basedir=basedir+"/"
+	mylist=[]
+	for myfile in entries["files"].keys():
+		if "cvs" in entries["files"][myfile]["status"]:
+			if "current" not in entries["files"][myfile]["status"]:
+				if "exists" in entries["files"][myfile]["status"]:
+					if entries["files"][myfile]["revision"]!="0":
+						mylist.append(basedir+myfile)
+	if recursive:
+		for mydir in entries["dirs"].keys():
+			mylist+=findchanged(entries["dirs"][mydir],recursive,basedir+mydir)
+	return mylist
+	
+def findmissing(entries,recursive=0,basedir=""):
+	"""(entries,recursive=0,basedir="")
+	Recurses the entries tree to find all elements that are listed in the cvs
+	tree but do not exist on the filesystem. Returns a list of paths,
+	optionally prepended with a basedir."""
+	if basedir and basedir[-1]!="/":
+		basedir=basedir+"/"
+	mylist=[]
+	for myfile in entries["files"].keys():
+		if "cvs" in entries["files"][myfile]["status"]:
+			if "exists" not in entries["files"][myfile]["status"]:
+				if "removed" not in entries["files"][myfile]["status"]:
+					mylist.append(basedir+myfile)
+	if recursive:
+		for mydir in entries["dirs"].keys():
+			mylist+=findmissing(entries["dirs"][mydir],recursive,basedir+mydir)
+	return mylist
+
+def findunadded(entries,recursive=0,basedir=""):
+	"""(entries,recursive=0,basedir="")
+	Recurses the entries tree to find all elements that are in valid cvs
+	directories but are not part of the cvs tree. Returns a list of paths,
+	optionally prepended with a basedir."""
+	if basedir and basedir[-1]!="/":
+		basedir=basedir+"/"
+	mylist=[]
+
+	#ignore what cvs ignores.
+	for myfile in entries["files"].keys():
+		if "cvs" not in entries["files"][myfile]["status"]:
+			mylist.append(basedir+myfile)
+	if recursive:
+		for mydir in entries["dirs"].keys():
+			mylist+=findunadded(entries["dirs"][mydir],recursive,basedir+mydir)
+	return mylist
+
+def findremoved(entries,recursive=0,basedir=""):
+	"""(entries,recursive=0,basedir="")
+	Recurses the entries tree to find all elements that are in flagged for cvs
+	deletions. Returns a list of paths,	optionally prepended with a basedir."""
+	if basedir and basedir[-1]!="/":
+		basedir=basedir+"/"
+	mylist=[]
+	for myfile in entries["files"].keys():
+		if "removed" in entries["files"][myfile]["status"]:
+			mylist.append(basedir+myfile)
+	if recursive:
+		for mydir in entries["dirs"].keys():
+			mylist+=findremoved(entries["dirs"][mydir],recursive,basedir+mydir)
+	return mylist
+
+def findall(entries, recursive=0, basedir=""):
+	"""(entries,recursive=0,basedir="")
+	Recurses the entries tree to find all new, changed, missing, and unadded
+	entities. Returns a 4 element list of lists as returned from each find*()."""
+
+	if basedir and basedir[-1]!="/":
+		basedir=basedir+"/"
+	mynew     = findnew(entries,recursive,basedir)
+	mychanged = findchanged(entries,recursive,basedir)
+	mymissing = findmissing(entries,recursive,basedir)
+	myunadded = findunadded(entries,recursive,basedir)
+	myremoved = findremoved(entries,recursive,basedir)
+	return [mynew, mychanged, mymissing, myunadded, myremoved]
+
+ignore_list = re.compile("(^|/)(RCS(|LOG)|SCCS|CVS(|\.adm)|cvslog\..*|tags|TAGS|\.(make\.state|nse_depinfo)|.*~|(\.|)#.*|,.*|_$.*|.*\$|\.del-.*|.*\.(old|BAK|bak|orig|rej|a|olb|o|obj|so|exe|Z|elc|ln)|core)$")
+def apply_cvsignore_filter(list):
+	x=0
+	while x < len(list):
+		if ignore_list.match(list[x].split("/")[-1]):
+			list.pop(x)
+		else:
+			x+=1
+	return list
+	
+def getentries(mydir,recursive=0):
+	"""(basedir,recursive=0)
+	Scans the given directory and returns an datadict of all the entries in
+	the directory seperated as a dirs dict and a files dict."""
+	myfn=mydir+"/CVS/Entries"
+	# entries=[dirs, files]
+	entries={"dirs":{},"files":{}}
+	if not os.path.exists(mydir):
+		return entries
+	try:
+		myfile=open(myfn, "r")
+		mylines=myfile.readlines()
+		myfile.close()
+	except SystemExit, e:
+		raise
+	except:
+		mylines=[]
+	for line in mylines:
+		if line and line[-1]=="\n":
+			line=line[:-1]
+		if not line:
+			continue
+		if line=="D": # End of entries file
+			break
+		mysplit=line.split("/")
+		if len(mysplit)!=6:
+			print "Confused:",mysplit
+			continue
+		if mysplit[0]=="D":
+			entries["dirs"][mysplit[1]]={"dirs":{},"files":{},"status":[]}
+			entries["dirs"][mysplit[1]]["status"]=["cvs"]
+			if os.path.isdir(mydir+"/"+mysplit[1]):
+				entries["dirs"][mysplit[1]]["status"]+=["exists"]
+				entries["dirs"][mysplit[1]]["flags"]=mysplit[2:]
+				if recursive:
+					rentries=getentries(mydir+"/"+mysplit[1],recursive)
+					#print rentries.keys()
+					#print entries["files"].keys()
+					#print entries["files"][mysplit[1]]
+					entries["dirs"][mysplit[1]]["dirs"]=rentries["dirs"]
+					entries["dirs"][mysplit[1]]["files"]=rentries["files"]
+		else:
+			# [D]/Name/revision/Date/Flags/Tags
+			entries["files"][mysplit[1]]={}
+			entries["files"][mysplit[1]]["revision"]=mysplit[2]
+			entries["files"][mysplit[1]]["date"]=mysplit[3]
+			entries["files"][mysplit[1]]["flags"]=mysplit[4]
+			entries["files"][mysplit[1]]["tags"]=mysplit[5]
+			entries["files"][mysplit[1]]["status"]=["cvs"]
+			if entries["files"][mysplit[1]]["revision"][0]=="-":
+				entries["files"][mysplit[1]]["status"]+=["removed"]
+
+	for file in apply_cvsignore_filter(os.listdir(mydir)):
+		if file=="CVS":
+			continue
+		if file=="digest-framerd-2.4.3":
+			print mydir,file
+		if os.path.isdir(mydir+"/"+file):
+			if not entries["dirs"].has_key(file):
+				entries["dirs"][file]={"dirs":{},"files":{}}
+			if entries["dirs"][file].has_key("status"):
+				if "exists" not in entries["dirs"][file]["status"]:
+					entries["dirs"][file]["status"]+=["exists"]
+			else:
+				entries["dirs"][file]["status"]=["exists"]
+		elif os.path.isfile(mydir+"/"+file):
+			if file=="digest-framerd-2.4.3":
+				print "isfile"
+			if not entries["files"].has_key(file):
+				entries["files"][file]={"revision":"","date":"","flags":"","tags":""}
+			if entries["files"][file].has_key("status"):
+				if file=="digest-framerd-2.4.3":
+					print "has status"
+				if "exists" not in entries["files"][file]["status"]:
+					if file=="digest-framerd-2.4.3":
+						print "no exists in status"
+					entries["files"][file]["status"]+=["exists"]
+			else:
+				if file=="digest-framerd-2.4.3":
+					print "no status"
+				entries["files"][file]["status"]=["exists"]
+			try:
+				if file=="digest-framerd-2.4.3":
+					print "stat'ing"
+				mystat=os.stat(mydir+"/"+file)
+				mytime=time.asctime(time.gmtime(mystat[ST_MTIME]))
+				if not entries["files"][file].has_key("status"):
+					if file=="digest-framerd-2.4.3":
+						print "status not set"
+					entries["files"][file]["status"]=[]
+				if file=="digest-framerd-2.4.3":
+					print "date:",entries["files"][file]["date"]
+					print "sdate:",mytime
+				if mytime==entries["files"][file]["date"]:
+					entries["files"][file]["status"]+=["current"]
+				if file=="digest-framerd-2.4.3":
+					print "stat done"
+				
+				del mystat
+			except SystemExit, e:
+				raise
+			except Exception, e:
+				print "failed to stat",file
+				print e
+				return
+				
+		else:
+			print
+			print "File of unknown type:",mydir+"/"+file
+			print
+	return entries
+
+#class cvstree:
+#	def __init__(self,basedir):
+#		self.refdir=os.cwd()
+#		self.basedir=basedir
+#		self.entries={}
+#		self.entries["dirs"]={}
+#		self.entries["files"]={}
+#		self.entries["dirs"][self.basedir]=getentries(self.basedir)
+#		self.getrealdirs(self.dirs, self.files)
+#	def getrealdirs(self,dirs,files):
+#		for mydir in dirs.keys():
+#			list = os.listdir(
+			
+		
Index: /vendor/portage/current/pym/dispatch_conf.py
===================================================================
--- /vendor/portage/current/pym/dispatch_conf.py	(revision 3419)
+++ /vendor/portage/current/pym/dispatch_conf.py	(revision 3419)
@@ -0,0 +1,161 @@
+# archive_conf.py -- functionality common to archive-conf and dispatch-conf
+# Copyright 2003-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: dispatch_conf.py 4850 2006-10-27 07:36:46Z zmedico $
+
+
+# Library by Wayne Davison <gentoo@blorf.net>, derived from code
+# written by Jeremy Wohl (http://igmus.org)
+
+from stat import *
+import os, sys, commands, shutil
+
+import portage
+
+RCS_BRANCH = '1.1.1'
+RCS_LOCK = 'rcs -ko -M -l'
+RCS_PUT = 'ci -t-"Archived config file." -m"dispatch-conf update."'
+RCS_GET = 'co'
+RCS_MERGE = 'rcsmerge -p -r' + RCS_BRANCH + ' %s >%s'
+
+DIFF3_MERGE = 'diff3 -mE %s %s %s >%s'
+
+def read_config(mandatory_opts):
+    try:
+        opts = portage.getconfig('/etc/dispatch-conf.conf')
+    except:
+        opts = None
+
+    if not opts:
+        print >> sys.stderr, 'dispatch-conf: Error reading /etc/dispatch-conf.conf; fatal'
+        sys.exit(1)
+
+    for key in mandatory_opts:
+        if not opts.has_key(key):
+            if key == "merge":
+                opts["merge"] = "sdiff --suppress-common-lines --output=%s %s %s"
+            else:
+                print >> sys.stderr, 'dispatch-conf: Missing option "%s" in /etc/dispatch-conf.conf; fatal' % (key,)
+
+    if not os.path.exists(opts['archive-dir']):
+        os.mkdir(opts['archive-dir'])
+    elif not os.path.isdir(opts['archive-dir']):
+        print >> sys.stderr, 'dispatch-conf: Config archive dir [%s] must exist; fatal' % (opts['archive-dir'],)
+        sys.exit(1)
+
+    return opts
+
+
+def rcs_archive(archive, curconf, newconf, mrgconf):
+    """Archive existing config in rcs (on trunk). Then, if mrgconf is
+    specified and an old branch version exists, merge the user's changes
+    and the distributed changes and put the result into mrgconf.  Lastly,
+    if newconf was specified, leave it in the archive dir with a .dist.new
+    suffix along with the last 1.1.1 branch version with a .dist suffix."""
+
+    try:
+        os.makedirs(os.path.dirname(archive))
+    except:
+        pass
+
+    try:
+        shutil.copy2(curconf, archive)
+    except(IOError, os.error), why:
+        print >> sys.stderr, 'dispatch-conf: Error copying %s to %s: %s; fatal' % \
+              (curconf, archive, str(why))
+    if os.path.exists(archive + ',v'):
+        os.system(RCS_LOCK + ' ' + archive)
+    os.system(RCS_PUT + ' ' + archive)
+
+    ret = 0
+    if newconf != '':
+        os.system(RCS_GET + ' -r' + RCS_BRANCH + ' ' + archive)
+        has_branch = os.path.exists(archive)
+        if has_branch:
+            os.rename(archive, archive + '.dist')
+
+        try:
+            shutil.copy2(newconf, archive)
+        except(IOError, os.error), why:
+            print >> sys.stderr, 'dispatch-conf: Error copying %s to %s: %s; fatal' % \
+                  (newconf, archive, str(why))
+
+        if has_branch:
+            if mrgconf != '':
+                # This puts the results of the merge into mrgconf.
+                ret = os.system(RCS_MERGE % (archive, mrgconf))
+                mystat = os.lstat(newconf)
+                os.chmod(mrgconf, mystat[ST_MODE])
+                os.chown(mrgconf, mystat[ST_UID], mystat[ST_GID])
+        os.rename(archive, archive + '.dist.new')
+    return ret
+
+
+def file_archive(archive, curconf, newconf, mrgconf):
+    """Archive existing config to the archive-dir, bumping old versions
+    out of the way into .# versions (log-rotate style). Then, if mrgconf
+    was specified and there is a .dist version, merge the user's changes
+    and the distributed changes and put the result into mrgconf.  Lastly,
+    if newconf was specified, archive it as a .dist.new version (which
+    gets moved to the .dist version at the end of the processing)."""
+
+    try:
+        os.makedirs(os.path.dirname(archive))
+    except:
+        pass
+
+    # Archive the current config file if it isn't already saved
+    if os.path.exists(archive) \
+     and len(commands.getoutput('diff -aq %s %s' % (curconf,archive))) != 0:
+        suf = 1
+        while suf < 9 and os.path.exists(archive + '.' + str(suf)):
+            suf += 1
+
+        while suf > 1:
+            os.rename(archive + '.' + str(suf-1), archive + '.' + str(suf))
+            suf -= 1
+
+        os.rename(archive, archive + '.1')
+
+    try:
+        shutil.copy2(curconf, archive)
+    except(IOError, os.error), why:
+        print >> sys.stderr, 'dispatch-conf: Error copying %s to %s: %s; fatal' % \
+              (curconf, archive, str(why))
+
+    if newconf != '':
+        # Save off new config file in the archive dir with .dist.new suffix
+        try:
+            shutil.copy2(newconf, archive + '.dist.new')
+        except(IOError, os.error), why:
+            print >> sys.stderr, 'dispatch-conf: Error copying %s to %s: %s; fatal' % \
+                  (newconf, archive + '.dist.new', str(why))
+
+        ret = 0
+        if mrgconf != '' and os.path.exists(archive + '.dist'):
+            # This puts the results of the merge into mrgconf.
+            ret = os.system(DIFF3_MERGE % (curconf, archive + '.dist', newconf, mrgconf))
+            mystat = os.lstat(newconf)
+            os.chmod(mrgconf, mystat[ST_MODE])
+            os.chown(mrgconf, mystat[ST_UID], mystat[ST_GID])
+
+        return ret
+
+
+def rcs_archive_post_process(archive):
+    """Check in the archive file with the .dist.new suffix on the branch
+    and remove the one with the .dist suffix."""
+    os.rename(archive + '.dist.new', archive)
+    if os.path.exists(archive + '.dist'):
+        # Commit the last-distributed version onto the branch.
+        os.system(RCS_LOCK + RCS_BRANCH + ' ' + archive)
+        os.system(RCS_PUT + ' -r' + RCS_BRANCH + ' ' + archive)
+        os.unlink(archive + '.dist')
+    else:
+        # Forcefully commit the last-distributed version onto the branch.
+        os.system(RCS_PUT + ' -f -r' + RCS_BRANCH + ' ' + archive)
+
+
+def file_archive_post_process(archive):
+    """Rename the archive file with the .dist.new suffix to a .dist suffix"""
+    os.rename(archive + '.dist.new', archive + '.dist')
Index: /vendor/portage/current/pym/eclass_cache.py
===================================================================
--- /vendor/portage/current/pym/eclass_cache.py	(revision 3419)
+++ /vendor/portage/current/pym/eclass_cache.py	(revision 3419)
@@ -0,0 +1,83 @@
+# Copyright: 2005 Gentoo Foundation
+# Author(s): Nicholas Carpaski (carpaski@gentoo.org), Brian Harring (ferringb@gentoo.org)
+# License: GPL2
+# $Id: eclass_cache.py 5583 2007-01-12 03:51:53Z antarus $
+
+from portage_util import normalize_path, writemsg
+import os, sys
+from portage_data import portage_gid
+
+class cache:
+	"""
+	Maintains the cache information about eclasses used in ebuild.
+	"""
+	def __init__(self, porttree_root, overlays=[]):
+		self.porttree_root = porttree_root
+
+		self.eclasses = {} # {"Name": ("location","_mtime_")}
+		self._eclass_locations = {}
+
+		# screw with the porttree ordering, w/out having bash inherit match it, and I'll hurt you.
+		# ~harring
+		self.porttrees = [self.porttree_root]+overlays
+		self.porttrees = tuple(map(normalize_path, self.porttrees))
+		self._master_eclass_root = os.path.join(self.porttrees[0],"eclass")
+		self.update_eclasses()
+
+	def close_caches(self):
+		import traceback
+		traceback.print_stack()
+		print "%s close_cache is deprecated" % self.__class__
+		self.eclasses.clear()
+
+	def flush_cache(self):
+		import traceback
+		traceback.print_stack()
+		print "%s flush_cache is deprecated" % self.__class__
+
+		self.update_eclasses()
+
+	def update_eclasses(self):
+		self.eclasses = {}
+		self._eclass_locations = {}
+		eclass_len = len(".eclass")
+		for x in [normalize_path(os.path.join(y,"eclass")) for y in self.porttrees]:
+			if not os.path.isdir(x):
+				continue
+			for y in [y for y in os.listdir(x) if y.endswith(".eclass")]:
+				try:
+					mtime = long(os.stat(os.path.join(x, y)).st_mtime)
+				except OSError:
+					continue
+				ys=y[:-eclass_len]
+				self.eclasses[ys] = (x, long(mtime))
+				self._eclass_locations[ys] = x
+	
+	def is_eclass_data_valid(self, ec_dict):
+		if not isinstance(ec_dict, dict):
+			return False
+		for eclass, tup in ec_dict.iteritems():
+			cached_data = self.eclasses.get(eclass, None)
+			""" Only use the mtime for validation since the probability of a
+			collision is small and, depending on the cache implementation, the
+			path may not be specified (cache from rsync mirrors, for example).
+			"""
+			if cached_data is None or tup[1] != cached_data[1]:
+				return False
+
+		return True
+
+	def get_eclass_data(self, inherits, from_master_only=False):
+		ec_dict = {}
+		for x in inherits:
+			try:
+				ec_dict[x] = self.eclasses[x]
+			except KeyError:
+				print "ec=",ec_dict
+				print "inherits=",inherits
+				raise
+			if from_master_only and \
+				self._eclass_locations[x] != self._master_eclass_root:
+				return None
+
+		return ec_dict
Index: /vendor/portage/current/pym/elog_modules/mod_custom.py
===================================================================
--- /vendor/portage/current/pym/elog_modules/mod_custom.py	(revision 3419)
+++ /vendor/portage/current/pym/elog_modules/mod_custom.py	(revision 3419)
@@ -0,0 +1,16 @@
+import elog_modules.mod_save, portage_exec, portage_exception
+
+def process(mysettings, cpv, logentries, fulltext):
+	elogfilename = elog_modules.mod_save.process(mysettings, cpv, logentries, fulltext)
+	
+	if (not "PORTAGE_ELOG_COMMAND" in mysettings.keys()) \
+			or len(mysettings["PORTAGE_ELOG_COMMAND"]) == 0:
+		raise portage_exception.MissingParameter("!!! Custom logging requested but PORTAGE_ELOG_COMMAND is not defined")
+	else:
+		mylogcmd = mysettings["PORTAGE_ELOG_COMMAND"]
+		mylogcmd = mylogcmd.replace("${LOGFILE}", elogfilename)
+		mylogcmd = mylogcmd.replace("${PACKAGE}", cpv)
+		retval = portage_exec.spawn_bash(mylogcmd)
+		if retval != 0:
+			raise portage_exception.PortageException("!!! PORTAGE_ELOG_COMMAND failed with exitcode %d" % retval)
+	return
Index: /vendor/portage/current/pym/elog_modules/mod_mail.py
===================================================================
--- /vendor/portage/current/pym/elog_modules/mod_mail.py	(revision 3419)
+++ /vendor/portage/current/pym/elog_modules/mod_mail.py	(revision 3419)
@@ -0,0 +1,22 @@
+# portage.py -- core Portage functionality
+# Copyright 1998-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: mod_mail.py 3484 2006-06-10 22:38:44Z genone $
+
+import portage_mail, socket
+
+def process(mysettings, cpv, logentries, fulltext):
+	if mysettings.has_key("PORTAGE_ELOG_MAILURI"):
+		myrecipient = mysettings["PORTAGE_ELOG_MAILURI"].split()[0]
+	else:
+		myrecipient = "root@localhost"
+	
+	myfrom = mysettings["PORTAGE_ELOG_MAILFROM"]
+	mysubject = mysettings["PORTAGE_ELOG_MAILSUBJECT"]
+	mysubject = mysubject.replace("${PACKAGE}", cpv)
+	mysubject = mysubject.replace("${HOST}", socket.getfqdn())
+
+	mymessage = portage_mail.create_message(myfrom, myrecipient, mysubject, fulltext)
+	portage_mail.send_mail(mysettings, mymessage)
+
+	return
Index: /vendor/portage/current/pym/elog_modules/mod_mail_summary.py
===================================================================
--- /vendor/portage/current/pym/elog_modules/mod_mail_summary.py	(revision 3419)
+++ /vendor/portage/current/pym/elog_modules/mod_mail_summary.py	(revision 3419)
@@ -0,0 +1,40 @@
+# portage.py -- core Portage functionality
+# Copyright 1998-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: mod_mail.py 3484 2006-06-10 22:38:44Z genone $
+
+import portage_mail, socket, os, time
+from email.MIMEText import MIMEText as TextMessage
+
+_items = {}
+def process(mysettings, cpv, logentries, fulltext):
+	header = ">>> Messages generated for package %s by process %d on %s:\n\n" % \
+		(cpv, os.getpid(), time.strftime("%Y%m%d-%H%M%S", time.gmtime(time.time())))
+	_items[cpv] = header + fulltext
+
+def finalize(mysettings):
+	if len(_items) == 0:
+		return
+	elif len(_items) == 1:
+		count = "one package"
+	else:
+		count = "multiple packages"
+	if mysettings.has_key("PORTAGE_ELOG_MAILURI"):
+		myrecipient = mysettings["PORTAGE_ELOG_MAILURI"].split()[0]
+	else:
+		myrecipient = "root@localhost"
+	
+	myfrom = mysettings["PORTAGE_ELOG_MAILFROM"]
+	mysubject = mysettings["PORTAGE_ELOG_MAILSUBJECT"]
+	mysubject = mysubject.replace("${PACKAGE}", count)
+	mysubject = mysubject.replace("${HOST}", socket.getfqdn())
+
+	mybody = "elog messages for the following packages generated by " + \
+		"process %d on host %s:\n" % (os.getpid(), socket.getfqdn())
+	for cpv in _items.keys():
+		 mybody += "- %s\n" % cpv
+
+	mymessage = portage_mail.create_message(myfrom, myrecipient, mysubject, mybody, attachments=_items.values())
+	portage_mail.send_mail(mysettings, mymessage)
+
+	return
Index: /vendor/portage/current/pym/elog_modules/mod_save.py
===================================================================
--- /vendor/portage/current/pym/elog_modules/mod_save.py	(revision 3419)
+++ /vendor/portage/current/pym/elog_modules/mod_save.py	(revision 3419)
@@ -0,0 +1,21 @@
+import os, time
+from portage_data import portage_uid, portage_gid
+
+def process(mysettings, cpv, logentries, fulltext):
+	cpv_path = cpv.replace("/", ":")
+
+	if mysettings["PORT_LOGDIR"] != "":
+		elogdir = os.path.join(mysettings["PORT_LOGDIR"], "elog")
+	else:
+		elogdir = os.path.join(os.sep, "var", "log", "portage", "elog")
+	if not os.path.exists(elogdir):
+		os.makedirs(elogdir)
+	os.chown(elogdir, portage_uid, portage_gid)
+	os.chmod(elogdir, 02770)
+
+	elogfilename = elogdir+"/"+cpv_path+":"+time.strftime("%Y%m%d-%H%M%S", time.gmtime(time.time()))+".log"
+	elogfile = open(elogfilename, "w")
+	elogfile.write(fulltext)
+	elogfile.close()
+
+	return elogfilename
Index: /vendor/portage/current/pym/elog_modules/mod_save_summary.py
===================================================================
--- /vendor/portage/current/pym/elog_modules/mod_save_summary.py	(revision 3419)
+++ /vendor/portage/current/pym/elog_modules/mod_save_summary.py	(revision 3419)
@@ -0,0 +1,23 @@
+import os, time
+from portage_data import portage_uid, portage_gid
+
+def process(mysettings, cpv, logentries, fulltext):
+	if mysettings["PORT_LOGDIR"] != "":
+		elogdir = os.path.join(mysettings["PORT_LOGDIR"], "elog")
+	else:
+		elogdir = os.path.join(os.sep, "var", "log", "portage", "elog")
+	if not os.path.exists(elogdir):
+		os.makedirs(elogdir)
+	os.chown(elogdir, portage_uid, portage_gid)
+	os.chmod(elogdir, 02770)
+
+	# TODO: Locking
+	elogfilename = elogdir+"/summary.log"
+	elogfile = open(elogfilename, "a")
+	elogfile.write(">>> Messages generated by process %d on %s for package %s:\n\n" % \
+			(os.getpid(), time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(time.time())), cpv))
+	elogfile.write(fulltext)
+	elogfile.write("\n")
+	elogfile.close()
+
+	return elogfilename
Index: /vendor/portage/current/pym/elog_modules/mod_syslog.py
===================================================================
--- /vendor/portage/current/pym/elog_modules/mod_syslog.py	(revision 3419)
+++ /vendor/portage/current/pym/elog_modules/mod_syslog.py	(revision 3419)
@@ -0,0 +1,17 @@
+import syslog
+from portage_const import EBUILD_PHASES
+
+def process(mysettings, cpv, logentries, fulltext):
+	syslog.openlog("portage", syslog.LOG_ERR | syslog.LOG_WARNING | syslog.LOG_INFO | syslog.LOG_NOTICE, syslog.LOG_LOCAL5)
+	for phase in EBUILD_PHASES:
+		if not phase in logentries:
+			continue
+		for msgtype,msgcontent in logentries[phase]:
+			pri = {"INFO": syslog.LOG_INFO, 
+				"WARN": syslog.LOG_WARNING, 
+				"ERROR": syslog.LOG_ERR, 
+				"LOG": syslog.LOG_NOTICE,
+				"QA": syslog.LOG_WARNING}
+			msgtext = "".join(msgcontent)
+			syslog.syslog(pri[msgtype], "%s: %s: %s" % (cpv, phase, msgtext))
+	syslog.closelog()
Index: /vendor/portage/current/pym/emergehelp.py
===================================================================
--- /vendor/portage/current/pym/emergehelp.py	(revision 3419)
+++ /vendor/portage/current/pym/emergehelp.py	(revision 3419)
@@ -0,0 +1,420 @@
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: emergehelp.py 5593 2007-01-12 06:49:45Z zmedico $
+
+
+import os,sys
+from output import bold, turquoise, green
+
+def shorthelp():
+	print
+	print
+	print bold("Usage:")
+	print "   "+turquoise("emerge")+" [ "+green("options")+" ] [ "+green("action")+" ] [ "+turquoise("ebuildfile")+" | "+turquoise("tbz2file")+" | "+turquoise("dependency")+" ] [ ... ]"
+	print "   "+turquoise("emerge")+" [ "+green("options")+" ] [ "+green("action")+" ] < "+turquoise("system")+" | "+turquoise("world")+" >"
+	print "   "+turquoise("emerge")+" < "+turquoise("--sync")+" | "+turquoise("--metadata")+" | "+turquoise("--info")+" >"
+	print "   "+turquoise("emerge")+" "+turquoise("--resume")+" [ "+green("--pretend")+" | "+green("--ask")+" | "+green("--skipfirst")+" ]"
+	print "   "+turquoise("emerge")+" "+turquoise("--help")+" [ "+green("system")+" | "+green("world")+" | "+green("config")+" | "+green("--sync")+" ] "
+	print bold("Options:")+" "+green("-")+"["+green("abBcCdDefgGhikKlnNoOpqPsStuvV")+"] ["+green("--oneshot")+"] ["+green("--newuse")+"] ["+green("--noconfmem")+"]"
+	print      "                                          [ " + green("--color")+" < " + turquoise("y") + " | "+ turquoise("n")+" >  ] [ "+green("--columns")+" ]"
+	print      "                                                                 ["+green("--nospinner")+"]"
+	print "                                          [ "+green("--deep")+"  ] [" + green("--with-bdeps")+" < " + turquoise("y") + " | "+ turquoise("n")+" > ]"
+	print bold("Actions:")+" [ "+green("--clean")+" | "+green("--depclean")+" | "+green("--prune")+" | "+green("--regen")+" | "+green("--search")+" | "+green("--unmerge")+" ]"
+	print
+
+def help(myaction,myopts,havecolor=1):
+	if not myaction and ("--help" not in myopts):
+		shorthelp()
+		print
+		print "   For more help try 'emerge --help' or consult the man page."
+		print
+	elif not myaction:
+		shorthelp()
+		print
+		print turquoise("Help (this screen):")
+		print "       "+green("--help")+" ("+green("-h")+" short option)"
+		print "              Displays this help; an additional argument (see above) will tell"
+		print "              emerge to display detailed help."
+		print
+		print turquoise("Actions:")
+		print "       "+green("--clean")+" ("+green("-c")+" short option)"
+		print "              Cleans the system by removing outdated packages which will not"
+		print "              remove functionalities or prevent your system from working."
+		print "              The arguments can be in several different formats :"
+		print "              * world "
+		print "              * system or"
+		print "              * 'dependency specification' (in single quotes is best.)"
+		print "              Here are a few examples of the dependency specification format:"
+		print "              "+bold("binutils")+" matches"
+		print "                  binutils-2.11.90.0.7 and binutils-2.11.92.0.12.3-r1"
+		print "              "+bold("sys-devel/binutils")+" matches"
+		print "                  binutils-2.11.90.0.7 and binutils-2.11.92.0.12.3-r1"
+		print "              "+bold(">sys-devel/binutils-2.11.90.0.7")+" matches"
+		print "                  binutils-2.11.92.0.12.3-r1"
+		print "              "+bold(">=sys-devel/binutils-2.11.90.0.7")+" matches"
+		print "                  binutils-2.11.90.0.7 and binutils-2.11.92.0.12.3-r1"
+		print "              "+bold("<=sys-devel/binutils-2.11.92.0.12.3-r1")+" matches"
+		print "                  binutils-2.11.90.0.7 and binutils-2.11.92.0.12.3-r1"
+		print
+		print "       "+green("--config")
+		print "              Runs package-specific operations that must be executed after an"
+		print "              emerge process has completed.  This usually entails configuration"
+		print "              file setup or other similar setups that the user may wish to run."
+		print
+		print "       "+green("--depclean")
+		print "              Cleans the system by removing packages that are not associated"
+		print "              with explicitly merged packages. Depclean works by creating the"
+		print "              full dependency tree from the system list and the world file,"
+		print "              then comparing it to installed packages. Packages installed, but"
+		print "              not associated with an explicit merge are listed as candidates"
+		print "              for unmerging."+turquoise(" WARNING: This can seriously affect your system by")
+		print "              "+turquoise("removing packages that may have been linked against, but due to")
+		print "              "+turquoise("changes in USE flags may no longer be part of the dep tree. Use")
+		print "              "+turquoise("caution when employing this feature.")
+		print
+		print "       "+green("--info")
+		print "              Displays important portage variables that will be exported to"
+		print "              ebuild.sh when performing merges. This information is useful"
+		print "              for bug reports and verification of settings. All settings in"
+		print "              make.{conf,globals,defaults} and the environment show up if"
+		print "              run with the '--verbose' flag."
+		print
+		print "       "+green("--metadata")
+		print "              Transfers metadata cache from ${PORTDIR}/metadata/cache/ to"
+		print "              /var/cache/edb/dep/ as is normally done on the tail end of an"
+		print "              rsync update using " + bold("emerge --sync") + ". This process populates the"
+		print "              cache database that portage uses for pre-parsed lookups of"
+		print "              package data.  It does not populate cache for the overlays"
+		print "              listed in PORTDIR_OVERLAY.  In order to generate cache for"
+		print "              overlays, use " + bold("--regen") + "."
+		print
+		print "       "+green("--prune")+" ("+green("-P")+" short option)"
+		print "              "+turquoise("WARNING: This action can remove important packages!")
+		print "              Removes all but the most recently installed version of a package"
+		print "              from your system. This action doesn't verify the possible binary"
+		print "              compatibility between versions and can thus remove essential"
+		print "              dependencies from your system."
+		print "              The argument format is the same as for the "+bold("--clean")+" action."
+		print
+		print "       "+green("--regen")
+		print "              Causes portage to check and update the dependency cache of all"
+		print "              ebuilds in the portage tree. This is not recommended for rsync"
+		print "              users as rsync updates the cache using server-side caches."
+		print "              Rsync users should simply 'emerge --sync' to regenerate."
+		print
+		print "       "+green("--resume")
+		print "              Resumes the last merge operation. It can be treated just like a"
+		print "              regular emerge: --pretend and other options work alongside it."
+		print "              'emerge --resume' only returns an error on failure. When there is"
+		print "              nothing to do, it exits with a message and a success condition."
+		print
+		print "       "+green("--search")+" ("+green("-s")+" short option)"
+		print "              Searches for matches of the supplied string in the current local"
+		print "              portage tree. By default emerge uses a case-insensitive simple "
+		print "              search, but you can enable a regular expression search by "
+		print "              prefixing the search string with %."
+		print "              Prepending the expression with a '@' will cause the category to"
+		print "              be included in the search."
+		print "              A few examples:"
+		print "              "+bold("emerge --search libc")
+		print "                  list all packages that contain libc in their name"
+		print "              "+bold("emerge --search '%^kde'")
+		print "                  list all packages starting with kde"
+		print "              "+bold("emerge --search '%gcc$'")
+		print "                  list all packages ending with gcc"
+		print "              "+bold("emerge --search '%@^dev-java.*jdk'")
+		print "                  list all available Java JDKs"
+		print
+		print "       "+green("--searchdesc")+" ("+green("-S")+" short option)"
+		print "              Matches the search string against the description field as well"
+		print "              the package's name. Take caution as the descriptions are also"
+		print "              matched as regular expressions."
+		print "                emerge -S html"
+		print "                emerge -S applet"
+		print "                emerge -S 'perl.*module'"
+		print
+		print "       "+green("--unmerge")+" ("+green("-C")+" short option)"
+		print "              "+turquoise("WARNING: This action can remove important packages!")
+		print "              Removes all matching packages "+bold("completely")+" from"
+		print "              your system. Specify arguments using the dependency specification"
+		print "              format described in the "+bold("--clean")+" action above."
+		print
+		print "       "+green("--update")+" ("+green("-u")+" short option)"
+		print "              Updates packages to the best version available, which may not"
+		print "              always be the highest version number due to masking for testing"
+		print "              and development. This will also update direct dependencies which"
+		print "              may not what you want. Package atoms specified on the command line"
+		print "              are greedy, meaning that unspecific atoms may match multiple"
+		print "              installed versions of slotted packages."
+		print
+		print "       "+green("--version")+" ("+green("-V")+" short option)"
+		print "              Displays the currently installed version of portage along with"
+		print "              other information useful for quick reference on a system. See"
+		print "              "+bold("emerge info")+" for more advanced information."
+		print
+		print turquoise("Options:")
+		print "       "+green("--alphabetical")
+		print "              When displaying USE and other flag output, combines the enabled"
+		print "              and disabled flags into a single list and sorts it alphabetically."
+		print "              With this option, output such as USE=\"dar -bar -foo\" will instead"
+		print "              be displayed as USE=\"-bar dar -foo\""
+		print
+		print "       "+green("--ask")+" ("+green("-a")+" short option)"
+		print "              before performing the merge, display what ebuilds and tbz2s will"
+		print "              be installed, in the same format as when using --pretend; then"
+		print "              ask whether to continue with the merge or abort. Using --ask is"
+		print "              more efficient than using --pretend and then executing the same"
+		print "              command without --pretend, as dependencies will only need to be"
+		print "              calculated once. WARNING: If the \"Enter\" key is pressed at the"
+		print "              prompt (with no other input), it is interpreted as acceptance of"
+		print "              the first choice.  Note that the input buffer is not cleared prior"
+		print "              to the prompt, so an accidental press of the \"Enter\" key at any"
+		print "              time prior to the prompt will be interpreted as a choice!"
+		print
+		print "       "+green("--buildpkg")+" ("+green("-b")+" short option)"
+		print "              Tell emerge to build binary packages for all ebuilds processed"
+		print "              (in addition to actually merging the packages.  Useful for"
+		print "              maintainers or if you administrate multiple Gentoo Linux"
+		print "              systems (build once, emerge tbz2s everywhere) as well as disaster"
+		print "              recovery."
+		print
+		print "       "+green("--buildpkgonly")+" ("+green("-B")+" short option)"
+		print "              Creates a binary package, but does not merge it to the"
+		print "              system. This has the restriction that unsatisfied dependencies"
+		print "              must not exist for the desired package as they cannot be used if"
+		print "              they do not exist on the system."
+		print
+		print "       "+green("--changelog")+" ("+green("-l")+" short option)"
+		print "              When pretending, also display the ChangeLog entries for packages"
+		print "              that will be upgraded."
+		print
+		print "       "+green("--color") + " < " + turquoise("y") + " | "+ turquoise("n")+" >"
+		print "              Enable or disable color output. This option will override NOCOLOR"
+		print "              (see make.conf(5)) and may also be used to force color output when"
+		print "              stdout is not a tty (by default, color is disabled unless stdout"
+		print "              is a tty)."
+		print
+		print "       "+green("--columns")
+		print "              Display the pretend output in a tabular form. Versions are"
+		print "              aligned vertically."
+		print
+		print "       "+green("--debug")+" ("+green("-d")+" short option)"
+		print "              Tell emerge to run the ebuild command in --debug mode. In this"
+		print "              mode, the bash build environment will run with the -x option,"
+		print "              causing it to output verbose debug information print to stdout."
+		print "              --debug is great for finding bash syntax errors as providing"
+		print "              very verbose information about the dependency and build process."
+		print
+		print "       "+green("--deep")+" ("+green("-D")+" short option)"
+		print "              This flag forces emerge to consider the entire dependency tree of"
+		print "              packages, instead of checking only the immediate dependencies of"
+		print "              the packages. As an example, this catches updates in libraries"
+		print "              that are not directly listed in the dependencies of a package."
+		print "              Also see --with-bdeps for behavior with respect to build time"
+		print "              dependencies that are not strictly required."
+		print 
+		print "       "+green("--emptytree")+" ("+green("-e")+" short option)"
+		print "              Virtually tweaks the tree of installed packages to contain"
+		print "              nothing. This is great to use together with --pretend. This makes"
+		print "              it possible for developers to get a complete overview of the"
+		print "              complete dependency tree of a certain package."
+		print
+		print "       "+green("--fetchonly")+" ("+green("-f")+" short option)"
+		print "              Instead of doing any package building, just perform fetches for"
+		print "              all packages (main package as well as all dependencies.) When"
+		print "              used in combination with --pretend all the SRC_URIs will be"
+		print "              displayed multiple mirrors per line, one line per file."
+		print
+		print "       "+green("--fetch-all-uri")+" ("+green("-F")+" short option)"
+		print "              Same as --fetchonly except that all package files, including those"
+		print "              not required to build the package, will be processed."
+		print
+		print "       "+green("--getbinpkg")+" ("+green("-g")+" short option)"
+		print "              Using the server and location defined in PORTAGE_BINHOST, portage"
+		print "              will download the information from each binary file there and it"
+		print "              will use that information to help build the dependency list. This"
+		print "              option implies '-k'. (Use -gK for binary-only merging.)"
+		print
+		print "       "+green("--getbinpkgonly")+" ("+green("-G")+" short option)"
+		print "              This option is identical to -g, as above, except it will not use"
+		print "              ANY information from the local machine. All binaries will be"
+		print "              downloaded from the remote server without consulting packages"
+		print "              existing in the packages directory."
+		print
+		print "       "+green("--newuse")+" ("+green("-N")+" short option)"
+		print "              Tells emerge to include installed packages where USE flags have "
+		print "              changed since installation."
+		print
+		print "       "+green("--noconfmem")
+		print "              Portage keeps track of files that have been placed into"
+		print "              CONFIG_PROTECT directories, and normally it will not merge the"
+		print "              same file more than once, as that would become annoying. This"
+		print "              can lead to problems when the user wants the file in the case"
+		print "              of accidental deletion. With this option, files will always be"
+		print "              merged to the live fs instead of silently dropped."
+		print
+		print "       "+green("--nodeps")+" ("+green("-O")+" short option)"
+		print "              Merge specified packages, but don't merge any dependencies."
+		print "              Note that the build may fail if deps aren't satisfied."
+		print 
+		print "       "+green("--noreplace")+" ("+green("-n")+" short option)"
+		print "              Skip the packages specified on the command-line that have"
+		print "              already been installed.  Without this option, any packages,"
+		print "              ebuilds, or deps you specify on the command-line *will* cause"
+		print "              Portage to remerge the package, even if it is already installed."
+		print "              Note that Portage won't remerge dependencies by default."
+		print 
+		print "       "+green("--nospinner")
+		print "              Disables the spinner regardless of terminal type."
+		print
+		print "       "+green("--oneshot")+" ("+green("-1")+" short option)"
+		print "              Emerge as normal, but don't add packages to the world profile."
+		print "              This package will only be updated if it is depended upon by"
+		print "              another package."
+		print
+		print "       "+green("--onlydeps")+" ("+green("-o")+" short option)"
+		print "              Only merge (or pretend to merge) the dependencies of the"
+		print "              specified packages, not the packages themselves."
+		print
+		print "       "+green("--pretend")+" ("+green("-p")+" short option)"
+		print "              Instead of actually performing the merge, simply display what"
+		print "              ebuilds and tbz2s *would* have been installed if --pretend"
+		print "              weren't used.  Using --pretend is strongly recommended before"
+		print "              installing an unfamiliar package.  In the printout, N = new,"
+		print "              U = updating, R = replacing, F = fetch  restricted, B = blocked"
+		print "              by an already installed package, D = possible downgrading,"
+		print "              S = slotted install. --verbose causes affecting use flags to be"
+		print "              printed out accompanied by a '+' for enabled and a '-' for"
+		print "              disabled USE flags."
+		print
+		print "       "+green("--quiet")+" ("+green("-q")+" short option)"
+		print "              Effects vary, but the general outcome is a reduced or condensed"
+		print "              output from portage's displays."
+		print
+		print "       "+green("--skipfirst")
+		print "              This option is only valid in a resume situation. It removes the"
+		print "              first package in the resume list so that a merge may continue in"
+		print "              the presence of an uncorrectable or inconsequential error. This"
+		print "              should only be used in cases where skipping the package will not"
+		print "              result in failed dependencies."
+		print
+		print "       "+green("--tree")+" ("+green("-t")+" short option)"
+		print "              Shows the dependency tree using indentation for dependencies."
+		print "              The packages are also listed in reverse merge order so that"
+		print "              a package's dependencies follow the package. Only really useful"
+		print "              in combination with --emptytree, --update or --deep."
+		print
+		print "       "+green("--usepkg")+" ("+green("-k")+" short option)"
+		print "              Tell emerge to use binary packages (from $PKGDIR) if they are"
+		print "              available, thus possibly avoiding some time-consuming compiles."
+		print "              This option is useful for CD installs; you can export"
+		print "              PKGDIR=/mnt/cdrom/packages and then use this option to have"
+		print "              emerge \"pull\" binary packages from the CD in order to satisfy" 
+		print "              dependencies."
+		print
+		print "       "+green("--usepkgonly")+" ("+green("-K")+" short option)"
+		print "              Like --usepkg above, except this only allows the use of binary"
+		print "              packages, and it will abort the emerge if the package is not"
+		print "              available at the time of dependency calculation."
+		print
+		print "       "+green("--verbose")+" ("+green("-v")+" short option)"
+		print "              Effects vary, but the general outcome is an increased or expanded"
+		print "              display of content in portage's displays."
+		print
+		print "       "+green("--with-bdeps")+" < " + turquoise("y") + " | "+ turquoise("n")+" >"
+		print "              In dependency calculations, pull in build time dependencies that"
+		print "              are not strictly required. This defaults to 'n' for installation"
+		print "              actions and 'y' for the --depclean action. This setting can be"
+		print "              added to EMERGE_DEFAULT_OPTS (see make.conf(5)) and later"
+		print "              overridden via the command line."
+		print
+	elif myaction == "sync":
+		print
+		print bold("Usage: ")+turquoise("emerge")+" "+turquoise("--sync")
+		print
+		print "       'emerge --sync' tells emerge to update the Portage tree as specified in"
+		print "       The SYNC variable found in /etc/make.conf.  By default, SYNC instructs"
+		print "       emerge to perform an rsync-style update with rsync.gentoo.org."
+		print
+		print "       'emerge-webrsync' exists as a helper app to emerge --sync, providing a"
+		print "       method to receive the entire portage tree as a tarball that can be"
+		print "       extracted and used. First time syncs would benefit greatly from this."
+		print
+		print "       "+turquoise("WARNING:")
+		print "       If using our rsync server, emerge will clean out all files that do not"
+		print "       exist on it, including ones that you may have created. The exceptions"
+		print "       to this are the distfiles, local and packages directories."
+		print
+	elif myaction=="system":
+		print
+		print bold("Usage: ")+turquoise("emerge")+" [ "+green("options")+" ] "+turquoise("system")
+		print
+		print "       \"emerge system\" is the Portage system update command.  When run, it"
+		print "       will scan the etc/make.profile/packages file and determine what"
+		print "       packages need to be installed so that your system meets the minimum"
+		print "       requirements of your current system profile.  Note that this doesn't"
+		print "       necessarily bring your system up-to-date at all; instead, it just"
+		print "       ensures that you have no missing parts.  For example, if your system"
+		print "       profile specifies that you should have sys-apps/iptables installed"
+		print "       and you don't, then \"emerge system\" will install it (the most"
+		print "       recent version that matches the profile spec) for you.  It's always a"
+		print "       good idea to do an \"emerge --pretend system\" before an \"emerge"
+		print "       system\", just so you know what emerge is planning to do."
+		print
+	elif myaction=="world":
+		print
+		print bold("Usage: ")+turquoise("emerge")+" [ "+green("options")+" ] "+turquoise("world")
+		print
+		print "       'emerge world' is the Portage command for completely updating your"
+		print "       system.  The normal procedure is to first do an 'emerge --sync' and"
+		print "       then an 'emerge --update --deep world'.  The first command brings your"
+		print "       local Portage tree up-to-date with the latest version information and"
+		print "       ebuilds.  The second command then rebuilds all packages for which newer"
+		print "       versions or newer ebuilds have become available since you last did a"
+		print "       sync and update."
+		print
+	elif myaction=="config":
+		outstuff=green("Config file management support (preliminary)")+"""
+
+Portage has a special feature called "config file protection".  The purpose of
+this feature is to prevent new package installs from clobbering existing
+configuration files.  By default, config file protection is turned on for /etc
+and the KDE configuration dirs; more may be added in the future.
+
+When Portage installs a file into a protected directory tree like /etc, any
+existing files will not be overwritten.  If a file of the same name already
+exists, Portage will change the name of the to-be-installed file from 'foo' to
+'._cfg0000_foo'.  If '._cfg0000_foo' already exists, this name becomes
+'._cfg0001_foo', etc.  In this way, existing files are not overwritten,
+allowing the administrator to manually merge the new config files and avoid any
+unexpected changes.
+
+In addition to protecting overwritten files, Portage will not delete any files
+from a protected directory when a package is unmerged.  While this may be a
+little bit untidy, it does prevent potentially valuable config files from being
+deleted, which is of paramount importance.
+
+Protected directories are set using the CONFIG_PROTECT variable, normally
+defined in /etc/make.globals.  Directory exceptions to the CONFIG_PROTECTed
+directories can be specified using the CONFIG_PROTECT_MASK variable.  To find
+files that need to be updated in /etc, type:
+
+# find /etc -iname '._cfg????_*'
+
+You can disable this feature by setting CONFIG_PROTECT="-*" in /etc/make.conf.
+Then, Portage will mercilessly auto-update your config files.  Alternatively,
+you can leave Config File Protection on but tell Portage that it can overwrite
+files in certain specific /etc subdirectories.  For example, if you wanted
+Portage to automatically update your rc scripts and your wget configuration,
+but didn't want any other changes made without your explicit approval, you'd
+add this to /etc/make.conf:
+
+CONFIG_PROTECT_MASK="/etc/wget /etc/rc.d"
+
+Tools such as dispatch-conf, cfg-update, and etc-update are also available to
+aid in the merging of these files. They provide interactive merging and can
+auto-merge trivial changes.
+
+"""
+		print outstuff
+
Index: /vendor/portage/current/pym/getbinpkg.py
===================================================================
--- /vendor/portage/current/pym/getbinpkg.py	(revision 3419)
+++ /vendor/portage/current/pym/getbinpkg.py	(revision 3419)
@@ -0,0 +1,572 @@
+# getbinpkg.py -- Portage binary-package helper functions
+# Copyright 2003-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: getbinpkg.py 5599 2007-01-12 08:29:09Z zmedico $
+
+if not hasattr(__builtins__, "set"):
+	from sets import Set as set
+
+from output import red, yellow, green
+import htmllib,HTMLParser,formatter,sys,os,xpak,time,tempfile,base64,urllib2
+
+try:
+	import cPickle
+except ImportError:
+	import pickle as cPickle
+
+try:
+	import ftplib
+except SystemExit, e:
+	raise
+except Exception, e:
+	sys.stderr.write(red("!!! CANNOT IMPORT FTPLIB: ")+str(e)+"\n")
+
+try:
+	import httplib
+except SystemExit, e:
+	raise
+except Exception, e:
+	sys.stderr.write(red("!!! CANNOT IMPORT HTTPLIB: ")+str(e)+"\n")
+
+def make_metadata_dict(data):
+	myid,myglob = data
+	
+	mydict = {}
+	for x in xpak.getindex_mem(myid):
+		mydict[x] = xpak.getitem(data,x)
+
+	return mydict
+
+class ParseLinks(HTMLParser.HTMLParser):
+	"""Parser class that overrides HTMLParser to grab all anchors from an html
+	page and provide suffix and prefix limitors"""
+	def __init__(self):
+		self.PL_anchors = []
+		HTMLParser.HTMLParser.__init__(self)
+
+	def get_anchors(self):
+		return self.PL_anchors
+		
+	def get_anchors_by_prefix(self,prefix):
+		newlist = []
+		for x in self.PL_anchors:
+			if x.startswith(prefix):
+				if x not in newlist:
+					newlist.append(x[:])
+		return newlist
+		
+	def get_anchors_by_suffix(self,suffix):
+		newlist = []
+		for x in self.PL_anchors:
+			if x.endswith(suffix):
+				if x not in newlist:
+					newlist.append(x[:])
+		return newlist
+		
+	def	handle_endtag(self,tag):
+		pass
+
+	def	handle_starttag(self,tag,attrs):
+		if tag == "a":
+			for x in attrs:
+				if x[0] == 'href':
+					if x[1] not in self.PL_anchors:
+						self.PL_anchors.append(urllib2.unquote(x[1]))
+
+
+def create_conn(baseurl,conn=None):
+	"""(baseurl,conn) --- Takes a protocol://site:port/address url, and an
+	optional connection. If connection is already active, it is passed on.
+	baseurl is reduced to address and is returned in tuple (conn,address)"""
+	parts = baseurl.split("://",1)
+	if len(parts) != 2:
+		raise ValueError, "Provided URL does not contain protocol identifier. '%s'" % baseurl
+	protocol,url_parts = parts
+	del parts
+	host,address = url_parts.split("/",1)
+	del url_parts
+	address = "/"+address
+
+	userpass_host = host.split("@",1)
+	if len(userpass_host) == 1:
+		host = userpass_host[0]
+		userpass = ["anonymous"]
+	else:
+		host = userpass_host[1]
+		userpass = userpass_host[0].split(":")
+	del userpass_host
+
+	if len(userpass) > 2:
+		raise ValueError, "Unable to interpret username/password provided."
+	elif len(userpass) == 2:
+		username = userpass[0]
+		password = userpass[1]
+	elif len(userpass) == 1:
+		username = userpass[0]
+		password = None
+	del userpass
+
+	http_headers = {}
+	http_params = {}
+	if username and password:
+		http_headers = {
+			"Authorization": "Basic %s" %
+			  base64.encodestring("%s:%s" % (username, password)).replace(
+			    "\012",
+			    ""
+			  ),
+		}
+
+	if not conn:
+		if protocol == "https":
+			conn = httplib.HTTPSConnection(host)
+		elif protocol == "http":
+			conn = httplib.HTTPConnection(host)
+		elif protocol == "ftp":
+			passive = 1
+			if(host[-1] == "*"):
+				passive = 0
+				host = host[:-1]
+			conn = ftplib.FTP(host)
+			if password:
+				conn.login(username,password)
+			else:
+				sys.stderr.write(yellow(" * No password provided for username")+" '"+str(username)+"'\n\n")
+				conn.login(username)
+			conn.set_pasv(passive)
+			conn.set_debuglevel(0)
+		else:
+			raise NotImplementedError, "%s is not a supported protocol." % protocol
+
+	return (conn,protocol,address, http_params, http_headers)
+
+def make_ftp_request(conn, address, rest=None, dest=None):
+	"""(conn,address,rest) --- uses the conn object to request the data
+	from address and issuing a rest if it is passed."""
+	try:
+	
+		if dest:
+			fstart_pos = dest.tell()
+	
+		conn.voidcmd("TYPE I")
+		fsize = conn.size(address)
+
+		if (rest != None) and (rest < 0):
+			rest = fsize+int(rest)
+		if rest < 0:
+			rest = 0
+
+		if rest != None:
+			mysocket = conn.transfercmd("RETR "+str(address), rest)
+		else:
+			mysocket = conn.transfercmd("RETR "+str(address))
+
+		mydata = ""
+		while 1:
+			somedata = mysocket.recv(8192)
+			if somedata:
+				if dest:
+					dest.write(somedata)
+				else:
+					mydata = mydata + somedata
+			else:
+				break
+
+		if dest:
+			data_size = fstart_pos - dest.tell()
+		else:
+			data_size = len(mydata)
+
+		mysocket.close()
+		conn.voidresp()
+		conn.voidcmd("TYPE A")
+
+		return mydata,not (fsize==data_size),""
+
+	except ValueError, e:
+		return None,int(str(e)[:4]),str(e)
+	
+
+def make_http_request(conn, address, params={}, headers={}, dest=None):
+	"""(conn,address,params,headers) --- uses the conn object to request
+	the data from address, performing Location forwarding and using the
+	optional params and headers."""
+
+	rc = 0
+	response = None
+	while (rc == 0) or (rc == 301) or (rc == 302):
+		try:
+			if (rc != 0):
+				conn,ignore,ignore,ignore,ignore = create_conn(address)
+			conn.request("GET", address, params, headers)
+		except SystemExit, e:
+			raise
+		except Exception, e:
+			return None,None,"Server request failed: "+str(e)
+		response = conn.getresponse()
+		rc = response.status
+
+		# 301 means that the page address is wrong.
+		if ((rc == 301) or (rc == 302)):
+			ignored_data = response.read()
+			del ignored_data
+			for x in str(response.msg).split("\n"):
+				parts = x.split(": ",1)
+				if parts[0] == "Location":
+					if (rc == 301):
+						sys.stderr.write(red("Location has moved: ")+str(parts[1])+"\n")
+					if (rc == 302):
+						sys.stderr.write(red("Location has temporarily moved: ")+str(parts[1])+"\n")
+					address = parts[1]
+					break
+	
+	if (rc != 200) and (rc != 206):
+		sys.stderr.write(str(response.msg)+"\n")
+		sys.stderr.write(response.read()+"\n")
+		sys.stderr.write("address: "+address+"\n")
+		return None,rc,"Server did not respond successfully ("+str(response.status)+": "+str(response.reason)+")"
+
+	if dest:
+		dest.write(response.read())
+		return "",0,""
+
+	return response.read(),0,""
+
+
+def match_in_array(array, prefix="", suffix="", match_both=1, allow_overlap=0):
+	myarray = []
+	
+	if not (prefix and suffix):
+		match_both = 0
+		
+	for x in array:
+		add_p = 0
+		if prefix and (len(x) >= len(prefix)) and (x[:len(prefix)] == prefix):
+			add_p = 1
+
+		if match_both:
+			if prefix and not add_p: # Require both, but don't have first one.
+				continue
+		else:
+			if add_p:     # Only need one, and we have it.
+				myarray.append(x[:])
+				continue
+
+		if not allow_overlap: # Not allow to overlap prefix and suffix
+			if len(x) >= (len(prefix)+len(suffix)):
+				y = x[len(prefix):]
+			else:
+				continue          # Too short to match.
+		else:
+			y = x               # Do whatever... We're overlapping.
+		
+		if suffix and (len(x) >= len(suffix)) and (x[-len(suffix):] == suffix):
+			myarray.append(x)   # It matches
+		else:
+			continue            # Doesn't match.
+
+	return myarray
+			
+
+
+def dir_get_list(baseurl,conn=None):
+	"""(baseurl[,connection]) -- Takes a base url to connect to and read from.
+	URL should be in the for <proto>://<site>[:port]<path>
+	Connection is used for persistent connection instances."""
+
+	if not conn:
+		keepconnection = 0
+	else:
+		keepconnection = 1
+
+	conn,protocol,address,params,headers = create_conn(baseurl, conn)
+
+	listing = None
+	if protocol in ["http","https"]:
+		page,rc,msg = make_http_request(conn,address,params,headers)
+		
+		if page:
+			parser = ParseLinks()
+			parser.feed(page)
+			del page
+			listing = parser.get_anchors()
+		else:
+			raise Exception, "Unable to get listing: %s %s" % (rc,msg)
+	elif protocol in ["ftp"]:
+		if address[-1] == '/':
+			olddir = conn.pwd()
+			conn.cwd(address)
+			listing = conn.nlst()
+			conn.cwd(olddir)
+			del olddir
+		else:
+			listing = conn.nlst(address)
+	else:
+		raise TypeError, "Unknown protocol. '%s'" % protocol
+
+	if not keepconnection:
+		conn.close()
+
+	return listing
+
+def file_get_metadata(baseurl,conn=None, chunk_size=3000):
+	"""(baseurl[,connection]) -- Takes a base url to connect to and read from.
+	URL should be in the for <proto>://<site>[:port]<path>
+	Connection is used for persistent connection instances."""
+
+	if not conn:
+		keepconnection = 0
+	else:
+		keepconnection = 1
+
+	conn,protocol,address,params,headers = create_conn(baseurl, conn)
+
+	if protocol in ["http","https"]:
+		headers["Range"] = "bytes=-"+str(chunk_size)
+		data,rc,msg = make_http_request(conn, address, params, headers)
+	elif protocol in ["ftp"]:
+		data,rc,msg = make_ftp_request(conn, address, -chunk_size)
+	else:
+		raise TypeError, "Unknown protocol. '%s'" % protocol
+	
+	if data:
+		xpaksize = xpak.decodeint(data[-8:-4])
+		if (xpaksize+8) > chunk_size:
+			myid = file_get_metadata(baseurl, conn, (xpaksize+8))
+			if not keepconnection:
+				conn.close()
+			return myid
+		else:
+			xpak_data = data[len(data)-(xpaksize+8):-8]
+		del data
+
+		myid = xpak.xsplit_mem(xpak_data)
+		if not myid:
+			myid = None,None
+		del xpak_data
+	else:
+		myid = None,None
+
+	if not keepconnection:
+		conn.close()
+
+	return myid
+
+
+def file_get(baseurl,dest,conn=None,fcmd=None):
+	"""(baseurl,dest,fcmd=) -- Takes a base url to connect to and read from.
+	URL should be in the for <proto>://[user[:pass]@]<site>[:port]<path>"""
+
+	if not fcmd:
+		return file_get_lib(baseurl,dest,conn)
+
+	fcmd = fcmd.replace("${DISTDIR}",dest)
+	fcmd = fcmd.replace("${URI}", baseurl)
+	fcmd = fcmd.replace("${FILE}", os.path.basename(baseurl))
+	mysplit = fcmd.split()
+	mycmd   = mysplit[0]
+	myargs  = [os.path.basename(mycmd)]+mysplit[1:]
+	mypid=os.fork()
+	if mypid == 0:
+		try:
+			os.execv(mycmd,myargs)
+		except OSError:
+			pass
+		sys.stderr.write("!!! Failed to spawn fetcher.\n")
+		sys.stderr.flush()
+		os._exit(1)
+	retval=os.waitpid(mypid,0)[1]
+	if (retval & 0xff) == 0:
+		retval = retval >> 8
+	else:
+		sys.stderr.write("Spawned processes caught a signal.\n")
+		sys.exit(1)
+	if retval != 0:
+		sys.stderr.write("Fetcher exited with a failure condition.\n")
+		return 0
+	return 1
+
+def file_get_lib(baseurl,dest,conn=None):
+	"""(baseurl[,connection]) -- Takes a base url to connect to and read from.
+	URL should be in the for <proto>://<site>[:port]<path>
+	Connection is used for persistent connection instances."""
+
+	if not conn:
+		keepconnection = 0
+	else:
+		keepconnection = 1
+
+	conn,protocol,address,params,headers = create_conn(baseurl, conn)
+
+	sys.stderr.write("Fetching '"+str(os.path.basename(address)+"'\n"))
+	if protocol in ["http","https"]:
+		data,rc,msg = make_http_request(conn, address, params, headers, dest=dest)
+	elif protocol in ["ftp"]:
+		data,rc,msg = make_ftp_request(conn, address, dest=dest)
+	else:
+		raise TypeError, "Unknown protocol. '%s'" % protocol
+	
+	if not keepconnection:
+		conn.close()
+
+	return rc
+
+
+def dir_get_metadata(baseurl, conn=None, chunk_size=3000, verbose=1, usingcache=1, makepickle=None):
+	"""(baseurl,conn,chunk_size,verbose) -- 
+	"""
+	if not conn:
+		keepconnection = 0
+	else:
+		keepconnection = 1
+
+	if makepickle is None:
+		makepickle = "/var/cache/edb/metadata.idx.most_recent"
+
+	conn,protocol,address,params,headers = create_conn(baseurl, conn)
+
+	filedict = {}
+
+	try:
+		metadatafile = open("/var/cache/edb/remote_metadata.pickle")
+		metadata = cPickle.load(metadatafile)
+		sys.stderr.write("Loaded metadata pickle.\n")
+		metadatafile.close()
+	except (cPickle.UnpicklingError, OSError, IOError, EOFError):
+		metadata = {}
+	if not metadata.has_key(baseurl):
+		metadata[baseurl]={}
+	if not metadata[baseurl].has_key("indexname"):
+		metadata[baseurl]["indexname"]=""
+	if not metadata[baseurl].has_key("timestamp"):
+		metadata[baseurl]["timestamp"]=0
+	if not metadata[baseurl].has_key("unmodified"):
+		metadata[baseurl]["unmodified"]=0
+	if not metadata[baseurl].has_key("data"):
+		metadata[baseurl]["data"]={}
+
+	filelist = dir_get_list(baseurl, conn)
+	tbz2list = match_in_array(filelist, suffix=".tbz2")
+	metalist = match_in_array(filelist, prefix="metadata.idx")
+	del filelist
+	
+	# Determine if our metadata file is current.
+	metalist.sort()
+	metalist.reverse() # makes the order new-to-old.
+	havecache=0
+	for mfile in metalist:
+		if usingcache and \
+		   ((metadata[baseurl]["indexname"] != mfile) or \
+			  (metadata[baseurl]["timestamp"] < int(time.time()-(60*60*24)))):
+			# Try to download new cache until we succeed on one.
+			data=""
+			for trynum in [1,2,3]:
+				mytempfile = tempfile.TemporaryFile()
+				try:
+					file_get(baseurl+"/"+mfile, mytempfile, conn)
+					if mytempfile.tell() > len(data):
+						mytempfile.seek(0)
+						data = mytempfile.read()
+				except ValueError, e:
+					sys.stderr.write("--- "+str(e)+"\n")
+					if trynum < 3:
+						sys.stderr.write("Retrying...\n")
+					mytempfile.close()
+					continue
+				if match_in_array([mfile],suffix=".gz"):
+					sys.stderr.write("gzip'd\n")
+					try:
+						import gzip
+						mytempfile.seek(0)
+						gzindex = gzip.GzipFile(mfile[:-3],'rb',9,mytempfile)
+						data = gzindex.read()
+					except SystemExit, e:
+						raise
+					except Exception, e:
+						mytempfile.close()
+						sys.stderr.write("!!! Failed to use gzip: "+str(e)+"\n")
+					mytempfile.close()
+				try:
+					metadata[baseurl]["data"] = cPickle.loads(data)
+					del data
+					metadata[baseurl]["indexname"] = mfile
+					metadata[baseurl]["timestamp"] = int(time.time())
+					metadata[baseurl]["modified"]  = 0 # It's not, right after download.
+					sys.stderr.write("Pickle loaded.\n")
+					break
+				except SystemExit, e:
+					raise
+				except Exception, e:
+					sys.stderr.write("!!! Failed to read data from index: "+str(mfile)+"\n")
+					sys.stderr.write("!!! "+str(e)+"\n")
+			try:
+				metadatafile = open("/var/cache/edb/remote_metadata.pickle", "w+")
+				cPickle.dump(metadata,metadatafile)
+				metadatafile.close()
+			except SystemExit, e:
+				raise
+			except Exception, e:
+				sys.stderr.write("!!! Failed to write binary metadata to disk!\n")
+				sys.stderr.write("!!! "+str(e)+"\n")
+			break
+	# We may have metadata... now we run through the tbz2 list and check.
+	sys.stderr.write(yellow("cache miss: 'x'")+" --- "+green("cache hit: 'o'")+"\n")
+	binpkg_filenames = set()
+	for x in tbz2list:
+		x = os.path.basename(x)
+		binpkg_filenames.add(x)
+		if ((not metadata[baseurl]["data"].has_key(x)) or \
+		    (x not in metadata[baseurl]["data"].keys())):
+			sys.stderr.write(yellow("x"))
+			metadata[baseurl]["modified"] = 1
+			myid = None
+			for retry in xrange(3):
+				try:
+					myid = file_get_metadata(
+						"/".join((baseurl.rstrip("/"), x.lstrip("/"))),
+						conn, chunk_size)
+					break
+				except httplib.BadStatusLine:
+					# Sometimes this error is thrown from conn.getresponse() in
+					# make_http_request().  The docstring for this error in
+					# httplib.py says "Presumably, the server closed the
+					# connection before sending a valid response".
+					conn, protocol, address, params, headers = create_conn(
+						baseurl)
+
+			if myid and myid[0]:
+				metadata[baseurl]["data"][x] = make_metadata_dict(myid)
+			elif verbose:
+				sys.stderr.write(red("!!! Failed to retrieve metadata on: ")+str(x)+"\n")
+		else:
+			sys.stderr.write(green("o"))
+	# Cleanse stale cache for files that don't exist on the server anymore.
+	stale_cache = set(metadata[baseurl]["data"]).difference(binpkg_filenames)
+	if stale_cache:
+		for x in stale_cache:
+			del metadata[baseurl]["data"][x]
+		metadata[baseurl]["modified"] = 1
+	del stale_cache
+	del binpkg_filenames
+	sys.stderr.write("\n")
+	
+	try:
+		if metadata[baseurl].has_key("modified") and metadata[baseurl]["modified"]:
+			metadata[baseurl]["timestamp"] = int(time.time())
+			metadatafile = open("/var/cache/edb/remote_metadata.pickle", "w+")
+			cPickle.dump(metadata,metadatafile)
+			metadatafile.close()
+		if makepickle:
+			metadatafile = open(makepickle, "w")
+			cPickle.dump(metadata[baseurl]["data"],metadatafile)
+			metadatafile.close()
+	except SystemExit, e:
+		raise
+	except Exception, e:
+		sys.stderr.write("!!! Failed to write binary metadata to disk!\n")
+		sys.stderr.write("!!! "+str(e)+"\n")
+
+	if not keepconnection:
+		conn.close()
+	
+	return metadata[baseurl]["data"]
Index: /vendor/portage/current/pym/output.py
===================================================================
--- /vendor/portage/current/pym/output.py	(revision 3419)
+++ /vendor/portage/current/pym/output.py	(revision 3419)
@@ -0,0 +1,396 @@
+# Copyright 1998-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: output.py 4906 2006-11-01 23:55:29Z zmedico $
+
+__docformat__ = "epytext"
+
+import commands,errno,os,re,shlex,sys
+from portage_const import COLOR_MAP_FILE
+from portage_util import writemsg
+from portage_exception import PortageException, ParseError, PermissionDenied, FileNotFound
+
+havecolor=1
+dotitles=1
+
+esc_seq = "\x1b["
+
+g_attr = {}
+g_attr["normal"]       =  0
+
+g_attr["bold"]         =  1
+g_attr["faint"]        =  2
+g_attr["standout"]     =  3
+g_attr["underline"]    =  4
+g_attr["blink"]        =  5
+g_attr["overline"]     =  6  # Why is overline actually useful?
+g_attr["reverse"]      =  7
+g_attr["invisible"]    =  8
+
+g_attr["no-attr"]      = 22
+g_attr["no-standout"]  = 23
+g_attr["no-underline"] = 24
+g_attr["no-blink"]     = 25
+g_attr["no-overline"]  = 26
+g_attr["no-reverse"]   = 27
+# 28 isn't defined?
+# 29 isn't defined?
+g_attr["black"]        = 30
+g_attr["red"]          = 31
+g_attr["green"]        = 32
+g_attr["yellow"]       = 33
+g_attr["blue"]         = 34
+g_attr["magenta"]      = 35
+g_attr["cyan"]         = 36
+g_attr["white"]        = 37
+# 38 isn't defined?
+g_attr["default"]      = 39
+g_attr["bg_black"]     = 40
+g_attr["bg_red"]       = 41
+g_attr["bg_green"]     = 42
+g_attr["bg_yellow"]    = 43
+g_attr["bg_blue"]      = 44
+g_attr["bg_magenta"]   = 45
+g_attr["bg_cyan"]      = 46
+g_attr["bg_white"]     = 47
+g_attr["bg_default"]   = 49
+
+
+# make_seq("blue", "black", "normal")
+def color(fg, bg="default", attr=["normal"]):
+	mystr = esc_seq[:] + "%02d" % g_attr[fg]
+	for x in [bg]+attr:
+		mystr += ";%02d" % g_attr[x]
+	return mystr+"m"
+
+
+
+codes={}
+codes["reset"]     = esc_seq + "39;49;00m"
+
+codes["bold"]      = esc_seq + "01m"
+codes["faint"]     = esc_seq + "02m"
+codes["standout"]  = esc_seq + "03m"
+codes["underline"] = esc_seq + "04m"
+codes["blink"]     = esc_seq + "05m"
+codes["overline"]  = esc_seq + "06m"  # Who made this up? Seriously.
+
+ansi_color_codes = []
+for x in xrange(30, 38):
+	ansi_color_codes.append("%im" % x)
+	ansi_color_codes.append("%i;01m" % x)
+
+rgb_ansi_colors = ['0x000000', '0x555555', '0xAA0000', '0xFF5555', '0x00AA00',
+	'0x55FF55', '0xAA5500', '0xFFFF55', '0x0000AA', '0x5555FF', '0xAA00AA',
+	'0xFF55FF', '0x00AAAA', '0x55FFFF', '0xAAAAAA', '0xFFFFFF']
+
+for x in xrange(len(rgb_ansi_colors)):
+	codes[rgb_ansi_colors[x]] = esc_seq + ansi_color_codes[x]
+
+del x
+
+codes["black"]     = codes["0x000000"]
+codes["darkgray"]  = codes["0x555555"]
+
+codes["red"]       = codes["0xFF5555"]
+codes["darkred"]   = codes["0xAA0000"]
+
+codes["green"]     = codes["0x55FF55"]
+codes["darkgreen"] = codes["0x00AA00"]
+
+codes["yellow"]    = codes["0xFFFF55"]
+codes["brown"]     = codes["0xAA5500"]
+
+codes["blue"]      = codes["0x5555FF"]
+codes["darkblue"]  = codes["0x0000AA"]
+
+codes["fuchsia"]   = codes["0xFF55FF"]
+codes["purple"]    = codes["0xAA00AA"]
+
+codes["turquoise"] = codes["0x55FFFF"]
+codes["teal"]      = codes["0x00AAAA"]
+
+codes["white"]     = codes["0xFFFFFF"]
+codes["lightgray"] = codes["0xAAAAAA"]
+
+codes["darkteal"]   = codes["turquoise"]
+codes["darkyellow"] = codes["brown"]
+codes["fuscia"]     = codes["fuchsia"]
+codes["white"]      = codes["bold"]
+
+# Colors from /sbin/functions.sh
+codes["GOOD"]       = codes["green"]
+codes["WARN"]       = codes["yellow"]
+codes["BAD"]        = codes["red"]
+codes["HILITE"]     = codes["teal"]
+codes["BRACKET"]    = codes["blue"]
+
+# Portage functions
+codes["INFORM"] = codes["darkgreen"]
+codes["UNMERGE_WARN"] = codes["red"]
+codes["MERGE_LIST_PROGRESS"] = codes["yellow"]
+
+def parse_color_map():
+	myfile = COLOR_MAP_FILE
+	ansi_code_pattern = re.compile("^[0-9;]*m$")
+	def strip_quotes(token, quotes):
+		if token[0] in quotes and token[0] == token[-1]:
+			token = token[1:-1]
+		return token
+	try:
+		s = shlex.shlex(open(myfile))
+		s.wordchars = s.wordchars + ";" # for ansi codes
+		d = {}
+		while True:
+			k, o, v = s.get_token(), s.get_token(), s.get_token()
+			if k is s.eof:
+				break
+			if o != "=":
+				raise ParseError("%s%s'%s'" % (s.error_leader(myfile, s.lineno), "expected '=' operator: ", o))
+			k = strip_quotes(k, s.quotes)
+			v = strip_quotes(v, s.quotes)
+			if ansi_code_pattern.match(v):
+				codes[k] = esc_seq + v
+			else:
+				if v in codes:
+					codes[k] = codes[v]
+				else:
+					raise ParseError("%s%s'%s'" % (s.error_leader(myfile, s.lineno), "Undefined: ", v))
+	except (IOError, OSError), e:
+		if e.errno == errno.ENOENT:
+			raise FileNotFound(myfile)
+		elif e.errno == errno.EACCES:
+			raise PermissionDenied(myfile)
+		raise
+
+try:
+	parse_color_map()
+except FileNotFound, e:
+	pass
+except PortageException, e:
+	writemsg("%s\n" % str(e))
+
+def nc_len(mystr):
+	tmp = re.sub(esc_seq + "^m]+m", "", mystr);
+	return len(tmp)
+
+def xtermTitle(mystr, raw=False):
+	if dotitles and "TERM" in os.environ and sys.stderr.isatty():
+		myt=os.environ["TERM"]
+		legal_terms = ["xterm","Eterm","aterm","rxvt","screen","kterm","rxvt-unicode","gnome"]
+		for term in legal_terms:
+			if myt.startswith(term):
+				if not raw:
+					mystr = "\x1b]0;%s\x07" % mystr
+				sys.stderr.write(mystr)
+				sys.stderr.flush()
+				break
+
+default_xterm_title = None
+
+def xtermTitleReset():
+	global default_xterm_title
+	if default_xterm_title is None:
+		prompt_command = os.getenv('PROMPT_COMMAND')
+		if prompt_command == "":
+			default_xterm_title = ""
+		elif prompt_command is not None:
+			default_xterm_title = commands.getoutput(prompt_command)
+		else:
+			pwd = os.getenv('PWD','')
+			home = os.getenv('HOME', '')
+			if home != '' and pwd.startswith(home):
+				pwd = '~' + pwd[len(home):]
+			default_xterm_title = '\x1b]0;%s@%s:%s\x07' % (
+				os.getenv('LOGNAME', ''), os.getenv('HOSTNAME', '').split('.', 1)[0], pwd)
+	xtermTitle(default_xterm_title, raw=True)
+
+def notitles():
+	"turn off title setting"
+	dotitles=0
+
+def nocolor():
+	"turn off colorization"
+	global havecolor
+	havecolor=0
+
+def resetColor():
+	return codes["reset"]
+
+def colorize(color_key, text):
+	global havecolor
+	if havecolor:
+		return codes[color_key] + text + codes["reset"]
+	else:
+		return text
+
+compat_functions_colors = ["bold","white","teal","turquoise","darkteal",
+	"fuscia","fuchsia","purple","blue","darkblue","green","darkgreen","yellow",
+	"brown","darkyellow","red","darkred"]
+
+def create_color_func(color_key):
+	def derived_func(*args):
+		newargs = list(args)
+		newargs.insert(0, color_key)
+		return colorize(*newargs)
+	return derived_func
+
+for c in compat_functions_colors:
+	setattr(sys.modules[__name__], c, create_color_func(c))
+
+class EOutput:
+	"""
+	Performs fancy terminal formatting for status and informational messages.
+
+	The provided methods produce identical terminal output to the eponymous
+	functions in the shell script C{/sbin/functions.sh} and also accept
+	identical parameters.
+
+	This is not currently a drop-in replacement however, as the output-related
+	functions in C{/sbin/functions.sh} are oriented for use mainly by system
+	init scripts and ebuilds and their output can be customized via certain
+	C{RC_*} environment variables (see C{/etc/conf.d/rc}). B{EOutput} is not
+	customizable in this manner since it's intended for more general uses.
+	Likewise, no logging is provided.
+
+	@ivar quiet: Specifies if output should be silenced.
+	@type quiet: BooleanType
+	@ivar term_columns: Width of terminal in characters. Defaults to the value
+		specified by the shell's C{COLUMNS} variable, else to the queried tty
+		size, else to C{80}.
+	@type term_columns: IntType
+	"""
+
+	def __init__(self):
+		self.__last_e_cmd = ""
+		self.__last_e_len = 0
+		self.quiet = False
+		columns = 0
+		try:
+			columns = int(os.getenv("COLUMNS", 0))
+		except ValueError:
+			pass
+		if columns <= 0:
+			try:
+				columns = int(commands.getoutput(
+					'set -- `stty size 2>/dev/null` ; echo "$2"'))
+			except ValueError:
+				pass
+		if columns <= 0:
+			columns = 80
+		# Adjust columns so that eend works properly on a standard BSD console.
+		if os.environ.get("TERM") == "cons25":
+			columns = columns - 1
+		self.term_columns = columns
+
+	def __eend(self, caller, errno, msg):
+		if errno == 0:
+			status_brackets = colorize("BRACKET", "[ ") + colorize("GOOD", "ok") + colorize("BRACKET", " ]")
+		else:
+			status_brackets = colorize("BRACKET", "[ ") + colorize("BAD", "!!") + colorize("BRACKET", " ]")
+			if msg:
+				if caller == "eend":
+					self.eerror(msg[0])
+				elif caller == "ewend":
+					self.ewarn(msg[0])
+		if self.__last_e_cmd != "ebegin":
+			self.__last_e_len = 0
+		print "%*s%s" % ((self.term_columns - self.__last_e_len - 6), "", status_brackets)
+		sys.stdout.flush()
+
+	def ebegin(self, msg):
+		"""
+		Shows a message indicating the start of a process.
+
+		@param msg: A very brief (shorter than one line) description of the
+			starting process.
+		@type msg: StringType
+		"""
+		msg += " ..."
+		if not self.quiet:
+			self.einfon(msg)
+		self.__last_e_len = len(msg) + 4
+		self.__last_e_cmd = "ebegin"
+
+	def eend(self, errno, *msg):
+		"""
+		Indicates the completion of a process, optionally displaying a message
+		via L{eerror} if the process's exit status isn't C{0}.
+
+		@param errno: A standard UNIX C{errno} code returned by processes upon
+			exit.
+		@type errno: IntType
+		@param msg: I{(optional)} An error message, typically a standard UNIX
+			error string corresponding to C{errno}.
+		@type msg: StringType
+		"""
+		if not self.quiet:
+			self.__eend("eend", errno, msg)
+		self.__last_e_cmd = "eend"
+
+	def eerror(self, msg):
+		"""
+		Shows an error message.
+
+		@param msg: A very brief (shorter than one line) error message.
+		@type msg: StringType
+		"""
+		if not self.quiet:
+			if self.__last_e_cmd == "ebegin": print
+			print colorize("BAD", " * ") + msg
+			sys.stdout.flush()
+		self.__last_e_cmd = "eerror"
+
+	def einfo(self, msg):
+		"""
+		Shows an informative message terminated with a newline.
+
+		@param msg: A very brief (shorter than one line) informative message.
+		@type msg: StringType
+		"""
+		if not self.quiet:
+			if self.__last_e_cmd == "ebegin": print
+			print colorize("GOOD", " * ") + msg
+			sys.stdout.flush()
+		self.__last_e_cmd = "einfo"
+
+	def einfon(self, msg):
+		"""
+		Shows an informative message terminated without a newline.
+
+		@param msg: A very brief (shorter than one line) informative message.
+		@type msg: StringType
+		"""
+		if not self.quiet:
+			if self.__last_e_cmd == "ebegin": print
+			print colorize("GOOD", " * ") + msg ,
+			sys.stdout.flush()
+		self.__last_e_cmd = "einfon"
+
+	def ewarn(self, msg):
+		"""
+		Shows a warning message.
+
+		@param msg: A very brief (shorter than one line) warning message.
+		@type msg: StringType
+		"""
+		if not self.quiet:
+			if self.__last_e_cmd == "ebegin": print
+			print colorize("WARN", " * ") + msg
+			sys.stdout.flush()
+		self.__last_e_cmd = "ewarn"
+
+	def ewend(self, errno, *msg):
+		"""
+		Indicates the completion of a process, optionally displaying a message
+		via L{ewarn} if the process's exit status isn't C{0}.
+
+		@param errno: A standard UNIX C{errno} code returned by processes upon
+			exit.
+		@type errno: IntType
+		@param msg: I{(optional)} A warning message, typically a standard UNIX
+			error string corresponding to C{errno}.
+		@type msg: StringType
+		"""
+		if not self.quiet:
+			self.__eend("ewend", errno, msg)
+		self.__last_e_cmd = "ewend"
Index: /vendor/portage/current/pym/portage.py
===================================================================
--- /vendor/portage/current/pym/portage.py	(revision 3419)
+++ /vendor/portage/current/pym/portage.py	(revision 3419)
@@ -0,0 +1,8353 @@
+# portage.py -- core Portage functionality
+# Copyright 1998-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: portage.py 5647 2007-01-14 22:03:17Z zmedico $
+
+
+VERSION="2.1.2"
+
+# ===========================================================================
+# START OF IMPORTS -- START OF IMPORTS -- START OF IMPORTS -- START OF IMPORT
+# ===========================================================================
+
+try:
+	import sys
+except ImportError:
+	print "Failed to import sys! Something is _VERY_ wrong with python."
+	raise
+
+try:
+	import copy, errno, os, re, shutil, time, types
+	try:
+		import cPickle
+	except ImportError:
+		import pickle as cPickle
+
+	import stat
+	import commands
+	from time import sleep
+	from random import shuffle
+	import UserDict
+	if getattr(__builtins__, "set", None) is None:
+		from sets import Set as set
+	from itertools import chain, izip
+except ImportError, e:
+	sys.stderr.write("\n\n")
+	sys.stderr.write("!!! Failed to complete python imports. These are internal modules for\n")
+	sys.stderr.write("!!! python and failure here indicates that you have a problem with python\n")
+	sys.stderr.write("!!! itself and thus portage is not able to continue processing.\n\n")
+
+	sys.stderr.write("!!! You might consider starting python with verbose flags to see what has\n")
+	sys.stderr.write("!!! gone wrong. Here is the information we got for this exception:\n")
+	sys.stderr.write("    "+str(e)+"\n\n");
+	raise
+
+try:
+	# XXX: This should get renamed to bsd_chflags, I think.
+	import chflags
+	bsd_chflags = chflags
+except ImportError:
+	bsd_chflags = None
+
+try:
+	from cache.cache_errors import CacheError
+	import cvstree
+	import xpak
+	import getbinpkg
+	import portage_dep
+	from portage_dep import dep_getcpv, dep_getkey, get_operator, \
+		isjustname, isspecific, isvalidatom, \
+		match_from_list, match_to_list, best_match_to_list
+
+	# XXX: This needs to get cleaned up.
+	import output
+	from output import bold, colorize, green, red, yellow
+
+	import portage_const
+	from portage_const import VDB_PATH, PRIVATE_PATH, CACHE_PATH, DEPCACHE_PATH, \
+	  USER_CONFIG_PATH, MODULES_FILE_PATH, CUSTOM_PROFILE_PATH, PORTAGE_BASE_PATH, \
+	  PORTAGE_BIN_PATH, PORTAGE_PYM_PATH, PROFILE_PATH, LOCALE_DATA_PATH, \
+	  EBUILD_SH_BINARY, SANDBOX_BINARY, BASH_BINARY, \
+	  MOVE_BINARY, PRELINK_BINARY, WORLD_FILE, MAKE_CONF_FILE, MAKE_DEFAULTS_FILE, \
+	  DEPRECATED_PROFILE_FILE, USER_VIRTUALS_FILE, EBUILD_SH_ENV_FILE, \
+	  INVALID_ENV_FILE, CUSTOM_MIRRORS_FILE, CONFIG_MEMORY_FILE,\
+	  INCREMENTALS, EAPI, MISC_SH_BINARY
+
+	from portage_data import ostype, lchown, userland, secpass, uid, wheelgid, \
+	                         portage_uid, portage_gid, userpriv_groups
+	from portage_manifest import Manifest
+
+	import portage_util
+	from portage_util import atomic_ofstream, apply_secpass_permissions, apply_recursive_permissions, \
+		dump_traceback, getconfig, grabdict, grabdict_package, grabfile, grabfile_package, \
+		map_dictlist_vals, new_protect_filename, normalize_path, \
+		pickle_read, pickle_write, stack_dictlist, stack_dicts, stack_lists, \
+		unique_array, varexpand, writedict, writemsg, writemsg_stdout, write_atomic
+	import portage_exception
+	import portage_gpg
+	import portage_locks
+	import portage_exec
+	from portage_exec import atexit_register, run_exitfuncs
+	from portage_locks import unlockfile,unlockdir,lockfile,lockdir
+	import portage_checksum
+	from portage_checksum import perform_md5,perform_checksum,prelink_capable
+	import eclass_cache
+	from portage_localization import _
+	from portage_update import dep_transform, fixdbentries, grab_updates, \
+		parse_updates, update_config_files, update_dbentries
+
+	# Need these functions directly in portage namespace to not break every external tool in existence
+	from portage_versions import best, catpkgsplit, catsplit, pkgcmp, \
+		pkgsplit, vercmp, ververify
+
+	# endversion and endversion_keys are for backward compatibility only.
+	from portage_versions import endversion_keys
+	from portage_versions import suffix_value as endversion
+
+except ImportError, e:
+	sys.stderr.write("\n\n")
+	sys.stderr.write("!!! Failed to complete portage imports. There are internal modules for\n")
+	sys.stderr.write("!!! portage and failure here indicates that you have a problem with your\n")
+	sys.stderr.write("!!! installation of portage. Please try a rescue portage located in the\n")
+	sys.stderr.write("!!! portage tree under '/usr/portage/sys-apps/portage/files/' (default).\n")
+	sys.stderr.write("!!! There is a README.RESCUE file that details the steps required to perform\n")
+	sys.stderr.write("!!! a recovery of portage.\n")
+	sys.stderr.write("    "+str(e)+"\n\n")
+	raise
+
+
+try:
+	import portage_selinux as selinux
+except OSError, e:
+	writemsg("!!! SELinux not loaded: %s\n" % str(e), noiselevel=-1)
+	del e
+except ImportError:
+	pass
+
+# ===========================================================================
+# END OF IMPORTS -- END OF IMPORTS -- END OF IMPORTS -- END OF IMPORTS -- END
+# ===========================================================================
+
+
+def load_mod(name):
+	modname = ".".join(name.split(".")[:-1])
+	mod = __import__(modname)
+	components = name.split('.')
+	for comp in components[1:]:
+		mod = getattr(mod, comp)
+	return mod
+
+def best_from_dict(key, top_dict, key_order, EmptyOnError=1, FullCopy=1, AllowEmpty=1):
+	for x in key_order:
+		if top_dict.has_key(x) and top_dict[x].has_key(key):
+			if FullCopy:
+				return copy.deepcopy(top_dict[x][key])
+			else:
+				return top_dict[x][key]
+	if EmptyOnError:
+		return ""
+	else:
+		raise KeyError, "Key not found in list; '%s'" % key
+
+def getcwd():
+	"this fixes situations where the current directory doesn't exist"
+	try:
+		return os.getcwd()
+	except OSError: #dir doesn't exist
+		os.chdir("/")
+		return "/"
+getcwd()
+
+def abssymlink(symlink):
+	"This reads symlinks, resolving the relative symlinks, and returning the absolute."
+	mylink=os.readlink(symlink)
+	if mylink[0] != '/':
+		mydir=os.path.dirname(symlink)
+		mylink=mydir+"/"+mylink
+	return os.path.normpath(mylink)
+
+dircache = {}
+cacheHit=0
+cacheMiss=0
+cacheStale=0
+def cacheddir(my_original_path, ignorecvs, ignorelist, EmptyOnError, followSymlinks=True):
+	global cacheHit,cacheMiss,cacheStale
+	mypath = normalize_path(my_original_path)
+	if dircache.has_key(mypath):
+		cacheHit += 1
+		cached_mtime, list, ftype = dircache[mypath]
+	else:
+		cacheMiss += 1
+		cached_mtime, list, ftype = -1, [], []
+	try:
+		pathstat = os.stat(mypath)
+		if stat.S_ISDIR(pathstat[stat.ST_MODE]):
+			mtime = pathstat[stat.ST_MTIME]
+		else:
+			raise portage_exception.DirectoryNotFound(mypath)
+	except (IOError,OSError,portage_exception.PortageException):
+		if EmptyOnError:
+			return [], []
+		return None, None
+	# Python retuns mtime in seconds, so if it was changed in the last few seconds, it could be invalid
+	if mtime != cached_mtime or time.time() - mtime < 4:
+		if dircache.has_key(mypath):
+			cacheStale += 1
+		list = os.listdir(mypath)
+		ftype = []
+		for x in list:
+			try:
+				if followSymlinks:
+					pathstat = os.stat(mypath+"/"+x)
+				else:
+					pathstat = os.lstat(mypath+"/"+x)
+
+				if stat.S_ISREG(pathstat[stat.ST_MODE]):
+					ftype.append(0)
+				elif stat.S_ISDIR(pathstat[stat.ST_MODE]):
+					ftype.append(1)
+				elif stat.S_ISLNK(pathstat[stat.ST_MODE]):
+					ftype.append(2)
+				else:
+					ftype.append(3)
+			except (IOError, OSError):
+				ftype.append(3)
+		dircache[mypath] = mtime, list, ftype
+
+	ret_list = []
+	ret_ftype = []
+	for x in range(0, len(list)):
+		if(ignorecvs and (len(list[x]) > 2) and (list[x][:2]!=".#")):
+			ret_list.append(list[x])
+			ret_ftype.append(ftype[x])
+		elif (list[x] not in ignorelist):
+			ret_list.append(list[x])
+			ret_ftype.append(ftype[x])
+
+	writemsg("cacheddirStats: H:%d/M:%d/S:%d\n" % (cacheHit, cacheMiss, cacheStale),10)
+	return ret_list, ret_ftype
+
+def listdir(mypath, recursive=False, filesonly=False, ignorecvs=False, ignorelist=[], followSymlinks=True,
+	EmptyOnError=False, dirsonly=False):
+	"""
+	Portage-specific implementation of os.listdir
+
+	@param mypath: Path whose contents you wish to list
+	@type mypath: String
+	@param recursive: Recursively scan directories contained within mypath
+	@type recursive: Boolean
+	@param filesonly; Only return files, not more directories
+	@type filesonly: Boolean
+	@param ignorecvs: Ignore CVS directories ('CVS','.svn','SCCS')
+	@type ignorecvs: Boolean
+	@param ignorelist: List of filenames/directories to exclude
+	@type ignorelist: List
+	@param followSymlinks: Follow Symlink'd files and directories
+	@type followSymlinks: Boolean
+	@param EmptyOnError: Return [] if an error occurs.
+	@type EmptyOnError: Boolean
+	@param dirsonly: Only return directories.
+	@type dirsonly: Boolean
+	@rtype: List
+	@returns: A list of files and directories (or just files or just directories) or an empty list.
+	"""
+
+	list, ftype = cacheddir(mypath, ignorecvs, ignorelist, EmptyOnError, followSymlinks)
+
+	if list is None:
+		list=[]
+	if ftype is None:
+		ftype=[]
+
+	if not (filesonly or dirsonly or recursive):
+		return list
+
+	if recursive:
+		x=0
+		while x<len(ftype):
+			if ftype[x]==1 and not (ignorecvs and os.path.basename(list[x]) in ('CVS','.svn','SCCS')):
+				l,f = cacheddir(mypath+"/"+list[x], ignorecvs, ignorelist, EmptyOnError,
+					followSymlinks)
+
+				l=l[:]
+				for y in range(0,len(l)):
+					l[y]=list[x]+"/"+l[y]
+				list=list+l
+				ftype=ftype+f
+			x+=1
+	if filesonly:
+		rlist=[]
+		for x in range(0,len(ftype)):
+			if ftype[x]==0:
+				rlist=rlist+[list[x]]
+	elif dirsonly:
+		rlist = []
+		for x in range(0, len(ftype)):
+			if ftype[x] == 1:
+				rlist = rlist + [list[x]]	
+	else:
+		rlist=list
+
+	return rlist
+
+def flatten(mytokens):
+	"""this function now turns a [1,[2,3]] list into
+	a [1,2,3] list and returns it."""
+	newlist=[]
+	for x in mytokens:
+		if type(x)==types.ListType:
+			newlist.extend(flatten(x))
+		else:
+			newlist.append(x)
+	return newlist
+
+#beautiful directed graph object
+
+class digraph:
+	def __init__(self):
+		"""Create an empty digraph"""
+		
+		# { node : ( { child : priority } , { parent : priority } ) }
+		self.nodes = {}
+		self.order = []
+
+	def add(self, node, parent, priority=0):
+		"""Adds the specified node with the specified parent.
+		
+		If the dep is a soft-dep and the node already has a hard
+		relationship to the parent, the relationship is left as hard."""
+		
+		if node not in self.nodes:
+			self.nodes[node] = ({}, {})
+			self.order.append(node)
+		
+		if not parent:
+			return
+		
+		if parent not in self.nodes:
+			self.nodes[parent] = ({}, {})
+			self.order.append(parent)
+		
+		if parent in self.nodes[node][1]:
+			if priority > self.nodes[node][1][parent]:
+				self.nodes[node][1][parent] = priority
+		else:
+			self.nodes[node][1][parent] = priority
+		
+		if node in self.nodes[parent][0]:
+			if priority > self.nodes[parent][0][node]:
+				self.nodes[parent][0][node] = priority
+		else:
+			self.nodes[parent][0][node] = priority
+
+	def remove(self, node):
+		"""Removes the specified node from the digraph, also removing
+		and ties to other nodes in the digraph. Raises KeyError if the
+		node doesn't exist."""
+		
+		if node not in self.nodes:
+			raise KeyError(node)
+		
+		for parent in self.nodes[node][1]:
+			del self.nodes[parent][0][node]
+		for child in self.nodes[node][0]:
+			del self.nodes[child][1][node]
+		
+		del self.nodes[node]
+		self.order.remove(node)
+
+	def contains(self, node):
+		"""Checks if the digraph contains mynode"""
+		return node in self.nodes
+
+	def all_nodes(self):
+		"""Return a list of all nodes in the graph"""
+		return self.order[:]
+
+	def child_nodes(self, node, ignore_priority=None):
+		"""Return all children of the specified node"""
+		if ignore_priority is None:
+			return self.nodes[node][0].keys()
+		children = []
+		for child, priority in self.nodes[node][0].iteritems():
+			if priority > ignore_priority:
+				children.append(child)
+		return children
+
+	def parent_nodes(self, node):
+		"""Return all parents of the specified node"""
+		return self.nodes[node][1].keys()
+
+	def leaf_nodes(self, ignore_priority=None):
+		"""Return all nodes that have no children
+		
+		If ignore_soft_deps is True, soft deps are not counted as
+		children in calculations."""
+		
+		leaf_nodes = []
+		for node in self.order:
+			is_leaf_node = True
+			for child in self.nodes[node][0]:
+				if self.nodes[node][0][child] > ignore_priority:
+					is_leaf_node = False
+					break
+			if is_leaf_node:
+				leaf_nodes.append(node)
+		return leaf_nodes
+
+	def root_nodes(self, ignore_priority=None):
+		"""Return all nodes that have no parents.
+		
+		If ignore_soft_deps is True, soft deps are not counted as
+		parents in calculations."""
+		
+		root_nodes = []
+		for node in self.order:
+			is_root_node = True
+			for parent in self.nodes[node][1]:
+				if self.nodes[node][1][parent] > ignore_priority:
+					is_root_node = False
+					break
+			if is_root_node:
+				root_nodes.append(node)
+		return root_nodes
+
+	def is_empty(self):
+		"""Checks if the digraph is empty"""
+		return len(self.nodes) == 0
+
+	def clone(self):
+		clone = digraph()
+		clone.nodes = copy.deepcopy(self.nodes)
+		clone.order = self.order[:]
+		return clone
+
+	# Backward compatibility
+	addnode = add
+	allnodes = all_nodes
+	allzeros = leaf_nodes
+	hasnode = contains
+	empty = is_empty
+	copy = clone
+
+	def delnode(self, node):
+		try:
+			self.remove(node)
+		except KeyError:
+			pass
+
+	def firstzero(self):
+		leaf_nodes = self.leaf_nodes()
+		if leaf_nodes:
+			return leaf_nodes[0]
+		return None
+
+	def hasallzeros(self, ignore_priority=None):
+		return len(self.leaf_nodes(ignore_priority=ignore_priority)) == \
+			len(self.order)
+
+	def debug_print(self):
+		for node in self.nodes:
+			print node,
+			if self.nodes[node][0]:
+				print "depends on"
+			else:
+				print "(no children)"
+			for child in self.nodes[node][0]:
+				print "  ",child,
+				print "(%s)" % self.nodes[node][0][child]
+
+
+_elog_atexit_handlers = []
+def elog_process(cpv, mysettings):
+	mylogfiles = listdir(mysettings["T"]+"/logging/")
+	# shortcut for packages without any messages
+	if len(mylogfiles) == 0:
+		return
+	# exploit listdir() file order so we process log entries in chronological order
+	mylogfiles.reverse()
+	mylogentries = {}
+	my_elog_classes = set(mysettings.get("PORTAGE_ELOG_CLASSES", "").split())
+	for f in mylogfiles:
+		msgfunction, msgtype = f.split(".")
+		if msgtype.upper() not in my_elog_classes \
+				and msgtype.lower() not in my_elog_classes:
+			continue
+		if msgfunction not in portage_const.EBUILD_PHASES:
+			writemsg("!!! can't process invalid log file: %s\n" % f,
+				noiselevel=-1)
+			continue
+		if not msgfunction in mylogentries:
+			mylogentries[msgfunction] = []
+		msgcontent = open(mysettings["T"]+"/logging/"+f, "r").readlines()
+		mylogentries[msgfunction].append((msgtype, msgcontent))
+
+	# in case the filters matched all messages
+	if len(mylogentries) == 0:
+		return
+
+	# generate a single string with all log messages
+	fulllog = ""
+	for phase in portage_const.EBUILD_PHASES:
+		if not phase in mylogentries:
+			continue
+		for msgtype,msgcontent in mylogentries[phase]:
+			fulllog += "%s: %s\n" % (msgtype, phase)
+			for line in msgcontent:
+				fulllog += line
+			fulllog += "\n"
+
+	# pass the processing to the individual modules
+	logsystems = mysettings["PORTAGE_ELOG_SYSTEM"].split()
+	for s in logsystems:
+		# - is nicer than _ for module names, so allow people to use it.
+		s = s.replace("-", "_")
+		try:
+			# FIXME: ugly ad.hoc import code
+			# TODO:  implement a common portage module loader
+			logmodule = __import__("elog_modules.mod_"+s)
+			m = getattr(logmodule, "mod_"+s)
+			def timeout_handler(signum, frame):
+				raise portage_exception.PortageException(
+					"Timeout in elog_process for system '%s'" % s)
+			import signal
+			signal.signal(signal.SIGALRM, timeout_handler)
+			# Timeout after one minute (in case something like the mail
+			# module gets hung).
+			signal.alarm(60)
+			try:
+				m.process(mysettings, cpv, mylogentries, fulllog)
+			finally:
+				signal.alarm(0)
+			if hasattr(m, "finalize") and not m.finalize in _elog_atexit_handlers:
+				_elog_atexit_handlers.append(m.finalize)
+				atexit_register(m.finalize, mysettings)
+		except (ImportError, AttributeError), e:
+			writemsg("!!! Error while importing logging modules " + \
+				"while loading \"mod_%s\":\n" % str(s))
+			writemsg("%s\n" % str(e), noiselevel=-1)
+		except portage_exception.PortageException, e:
+			writemsg("%s\n" % str(e), noiselevel=-1)
+
+	# clean logfiles to avoid repetitions
+	for f in mylogfiles:
+		try:
+			os.unlink(os.path.join(mysettings["T"], "logging", f))
+		except OSError:
+			pass
+
+#parse /etc/env.d and generate /etc/profile.env
+
+def env_update(makelinks=1, target_root=None, prev_mtimes=None, contents=None):
+	if target_root is None:
+		global root
+		target_root = root
+	if prev_mtimes is None:
+		global mtimedb
+		prev_mtimes = mtimedb["ldpath"]
+	envd_dir = os.path.join(target_root, "etc", "env.d")
+	portage_util.ensure_dirs(envd_dir, mode=0755)
+	fns = listdir(envd_dir, EmptyOnError=1)
+	fns.sort()
+	templist = []
+	for x in fns:
+		if len(x) < 3:
+			continue
+		if not x[0].isdigit() or not x[1].isdigit():
+			continue
+		if x.startswith(".") or x.endswith("~") or x.endswith(".bak"):
+			continue
+		templist.append(x)
+	fns = templist
+	del templist
+
+	space_separated = set(["CONFIG_PROTECT", "CONFIG_PROTECT_MASK"])
+	colon_separated = set(["ADA_INCLUDE_PATH", "ADA_OBJECTS_PATH",
+		"CLASSPATH", "INFODIR", "INFOPATH", "KDEDIRS", "LDPATH", "MANPATH",
+		  "PATH", "PKG_CONFIG_PATH", "PRELINK_PATH", "PRELINK_PATH_MASK",
+		  "PYTHONPATH", "ROOTPATH"])
+
+	config_list = []
+
+	for x in fns:
+		file_path = os.path.join(envd_dir, x)
+		try:
+			myconfig = getconfig(file_path, expand=False)
+		except portage_exception.ParseError, e:
+			writemsg("!!! '%s'\n" % str(e), noiselevel=-1)
+			del e
+			continue
+		if myconfig is None:
+			# broken symlink or file removed by a concurrent process
+			writemsg("!!! File Not Found: '%s'\n" % file_path, noiselevel=-1)
+			continue
+		config_list.append(myconfig)
+		if "SPACE_SEPARATED" in myconfig:
+			space_separated.update(myconfig["SPACE_SEPARATED"].split())
+			del myconfig["SPACE_SEPARATED"]
+		if "COLON_SEPARATED" in myconfig:
+			colon_separated.update(myconfig["COLON_SEPARATED"].split())
+			del myconfig["COLON_SEPARATED"]
+
+	env = {}
+	specials = {}
+	for var in space_separated:
+		mylist = []
+		for myconfig in config_list:
+			if var in myconfig:
+				mylist.extend(filter(None, myconfig[var].split()))
+				del myconfig[var] # prepare for env.update(myconfig)
+		if mylist:
+			env[var] = " ".join(mylist)
+		specials[var] = mylist
+
+	for var in colon_separated:
+		mylist = []
+		for myconfig in config_list:
+			if var in myconfig:
+				mylist.extend(filter(None, myconfig[var].split(":")))
+				del myconfig[var] # prepare for env.update(myconfig)
+		if mylist:
+			env[var] = ":".join(mylist)
+		specials[var] = mylist
+
+	for myconfig in config_list:
+		"""Cumulative variables have already been deleted from myconfig so that
+		they won't be overwritten by this dict.update call."""
+		env.update(myconfig)
+
+	ldsoconf_path = os.path.join(target_root, "etc", "ld.so.conf")
+	try:
+		myld = open(ldsoconf_path)
+		myldlines=myld.readlines()
+		myld.close()
+		oldld=[]
+		for x in myldlines:
+			#each line has at least one char (a newline)
+			if x[0]=="#":
+				continue
+			oldld.append(x[:-1])
+	except (IOError, OSError), e:
+		if e.errno != errno.ENOENT:
+			raise
+		oldld = None
+
+	ld_cache_update=False
+
+	newld = specials["LDPATH"]
+	if (oldld!=newld):
+		#ld.so.conf needs updating and ldconfig needs to be run
+		myfd = atomic_ofstream(ldsoconf_path)
+		myfd.write("# ld.so.conf autogenerated by env-update; make all changes to\n")
+		myfd.write("# contents of /etc/env.d directory\n")
+		for x in specials["LDPATH"]:
+			myfd.write(x+"\n")
+		myfd.close()
+		ld_cache_update=True
+
+	# Update prelink.conf if we are prelink-enabled
+	if prelink_capable:
+		newprelink = atomic_ofstream(
+			os.path.join(target_root, "etc", "prelink.conf"))
+		newprelink.write("# prelink.conf autogenerated by env-update; make all changes to\n")
+		newprelink.write("# contents of /etc/env.d directory\n")
+
+		for x in ["/bin","/sbin","/usr/bin","/usr/sbin","/lib","/usr/lib"]:
+			newprelink.write("-l "+x+"\n");
+		for x in specials["LDPATH"]+specials["PATH"]+specials["PRELINK_PATH"]:
+			if not x:
+				continue
+			if x[-1]!='/':
+				x=x+"/"
+			plmasked=0
+			for y in specials["PRELINK_PATH_MASK"]:
+				if not y:
+					continue
+				if y[-1]!='/':
+					y=y+"/"
+				if y==x[0:len(y)]:
+					plmasked=1
+					break
+			if not plmasked:
+				newprelink.write("-h "+x+"\n")
+		for x in specials["PRELINK_PATH_MASK"]:
+			newprelink.write("-b "+x+"\n")
+		newprelink.close()
+
+	# Portage stores mtimes with 1 second granularity but in >=python-2.5 finer
+	# granularity is possible.  In order to avoid the potential ambiguity of
+	# mtimes that differ by less than 1 second, sleep here if any of the
+	# directories have been modified during the current second.
+	sleep_for_mtime_granularity = False
+	current_time = long(time.time())
+	mtime_changed = False
+	lib_dirs = set()
+	for lib_dir in portage_util.unique_array(specials["LDPATH"]+['usr/lib','usr/lib64','usr/lib32','lib','lib64','lib32']):
+		x = os.path.join(target_root, lib_dir.lstrip(os.sep))
+		try:
+			newldpathtime = long(os.stat(x).st_mtime)
+			lib_dirs.add(normalize_path(x))
+		except OSError, oe:
+			if oe.errno == errno.ENOENT:
+				try:
+					del prev_mtimes[x]
+				except KeyError:
+					pass
+				# ignore this path because it doesn't exist
+				continue
+			raise
+		if newldpathtime == current_time:
+			sleep_for_mtime_granularity = True
+		if x in prev_mtimes:
+			if prev_mtimes[x] == newldpathtime:
+				pass
+			else:
+				prev_mtimes[x] = newldpathtime
+				mtime_changed = True
+		else:
+			prev_mtimes[x] = newldpathtime
+			mtime_changed = True
+
+	if mtime_changed:
+		ld_cache_update = True
+
+	if makelinks and \
+		not ld_cache_update and \
+		contents is not None:
+		libdir_contents_changed = False
+		for mypath, mydata in contents.iteritems():
+			if mydata[0] not in ("obj","sym"):
+				continue
+			head, tail = os.path.split(mypath)
+			if head in lib_dirs:
+				libdir_contents_changed = True
+				break
+		if not libdir_contents_changed:
+			makelinks = False
+
+	# Only run ldconfig as needed
+	if (ld_cache_update or makelinks):
+		# ldconfig has very different behaviour between FreeBSD and Linux
+		if ostype=="Linux" or ostype.lower().endswith("gnu"):
+			# We can't update links if we haven't cleaned other versions first, as
+			# an older package installed ON TOP of a newer version will cause ldconfig
+			# to overwrite the symlinks we just made. -X means no links. After 'clean'
+			# we can safely create links.
+			writemsg(">>> Regenerating %setc/ld.so.cache...\n" % target_root)
+			if makelinks:
+				commands.getstatusoutput("cd / ; /sbin/ldconfig -r '%s'" % target_root)
+			else:
+				commands.getstatusoutput("cd / ; /sbin/ldconfig -X -r '%s'" % target_root)
+		elif ostype in ("FreeBSD","DragonFly"):
+			writemsg(">>> Regenerating %svar/run/ld-elf.so.hints...\n" % target_root)
+			commands.getstatusoutput(
+				"cd / ; /sbin/ldconfig -elf -i -f '%svar/run/ld-elf.so.hints' '%setc/ld.so.conf'" % \
+				(target_root, target_root))
+
+	del specials["LDPATH"]
+
+	penvnotice  = "# THIS FILE IS AUTOMATICALLY GENERATED BY env-update.\n"
+	penvnotice += "# DO NOT EDIT THIS FILE. CHANGES TO STARTUP PROFILES\n"
+	cenvnotice  = penvnotice[:]
+	penvnotice += "# GO INTO /etc/profile NOT /etc/profile.env\n\n"
+	cenvnotice += "# GO INTO /etc/csh.cshrc NOT /etc/csh.env\n\n"
+
+	#create /etc/profile.env for bash support
+	outfile = atomic_ofstream(os.path.join(target_root, "etc", "profile.env"))
+	outfile.write(penvnotice)
+
+	env_keys = [ x for x in env if x != "LDPATH" ]
+	env_keys.sort()
+	for x in env_keys:
+		outfile.write("export %s='%s'\n" % (x, env[x]))
+	outfile.close()
+
+	#create /etc/csh.env for (t)csh support
+	outfile = atomic_ofstream(os.path.join(target_root, "etc", "csh.env"))
+	outfile.write(cenvnotice)
+	for x in env_keys:
+		outfile.write("setenv %s '%s'\n" % (x, env[x]))
+	outfile.close()
+
+	if sleep_for_mtime_granularity:
+		while current_time == long(time.time()):
+			sleep(1)
+
+def ExtractKernelVersion(base_dir):
+	"""
+	Try to figure out what kernel version we are running
+	@param base_dir: Path to sources (usually /usr/src/linux)
+	@type base_dir: string
+	@rtype: tuple( version[string], error[string])
+	@returns:
+	1. tuple( version[string], error[string])
+	Either version or error is populated (but never both)
+
+	"""
+	lines = []
+	pathname = os.path.join(base_dir, 'Makefile')
+	try:
+		f = open(pathname, 'r')
+	except OSError, details:
+		return (None, str(details))
+	except IOError, details:
+		return (None, str(details))
+
+	try:
+		for i in range(4):
+			lines.append(f.readline())
+	except OSError, details:
+		return (None, str(details))
+	except IOError, details:
+		return (None, str(details))
+
+	lines = [l.strip() for l in lines]
+
+	version = ''
+
+	#XXX: The following code relies on the ordering of vars within the Makefile
+	for line in lines:
+		# split on the '=' then remove annoying whitespace
+		items = line.split("=")
+		items = [i.strip() for i in items]
+		if items[0] == 'VERSION' or \
+			items[0] == 'PATCHLEVEL':
+			version += items[1]
+			version += "."
+		elif items[0] == 'SUBLEVEL':
+			version += items[1]
+		elif items[0] == 'EXTRAVERSION' and \
+			items[-1] != items[0]:
+			version += items[1]
+
+	# Grab a list of files named localversion* and sort them
+	localversions = os.listdir(base_dir)
+	for x in range(len(localversions)-1,-1,-1):
+		if localversions[x][:12] != "localversion":
+			del localversions[x]
+	localversions.sort()
+
+	# Append the contents of each to the version string, stripping ALL whitespace
+	for lv in localversions:
+		version += "".join( " ".join( grabfile( base_dir+ "/" + lv ) ).split() )
+
+	# Check the .config for a CONFIG_LOCALVERSION and append that too, also stripping whitespace
+	kernelconfig = getconfig(base_dir+"/.config")
+	if kernelconfig and kernelconfig.has_key("CONFIG_LOCALVERSION"):
+		version += "".join(kernelconfig["CONFIG_LOCALVERSION"].split())
+
+	return (version,None)
+
+def autouse(myvartree, use_cache=1, mysettings=None):
+	"""
+	autuse returns a list of USE variables auto-enabled to packages being installed
+
+	@param myvartree: Instance of the vartree class (from /var/db/pkg...)
+	@type myvartree: vartree
+	@param use_cache: read values from cache
+	@type use_cache: Boolean
+	@param mysettings: Instance of config
+	@type mysettings: config
+	@rtype: string
+	@returns: A string containing a list of USE variables that are enabled via use.defaults
+	"""
+	if mysettings is None:
+		global settings
+		mysettings = settings
+	if mysettings.profile_path is None:
+		return ""
+	myusevars=""
+	usedefaults = mysettings.use_defs
+	for myuse in usedefaults:
+		dep_met = True
+		for mydep in usedefaults[myuse]:
+			if not myvartree.dep_match(mydep,use_cache=True):
+				dep_met = False
+				break
+		if dep_met:
+			myusevars += " "+myuse
+	return myusevars
+
+def check_config_instance(test):
+	if not test or (str(test.__class__) != 'portage.config'):
+		raise TypeError, "Invalid type for config object: %s" % test.__class__
+
+class config:
+	"""
+	This class encompasses the main portage configuration.  Data is pulled from
+	ROOT/PORTDIR/profiles/, from ROOT/etc/make.profile incrementally through all 
+	parent profiles as well as from ROOT/PORTAGE_CONFIGROOT/* for user specified
+	overrides.
+	
+	Generally if you need data like USE flags, FEATURES, environment variables,
+	virtuals ...etc you look in here.
+	"""
+	
+	def __init__(self, clone=None, mycpv=None, config_profile_path=None,
+		config_incrementals=None, config_root=None, target_root=None,
+		local_config=True):
+		"""
+		@param clone: If provided, init will use deepcopy to copy by value the instance.
+		@type clone: Instance of config class.
+		@param mycpv: CPV to load up (see setcpv), this is the same as calling init with mycpv=None
+		and then calling instance.setcpv(mycpv).
+		@type mycpv: String
+		@param config_profile_path: Configurable path to the profile (usually PROFILE_PATH from portage_const)
+		@type config_profile_path: String
+		@param config_incrementals: List of incremental variables (usually portage_const.INCREMENTALS)
+		@type config_incrementals: List
+		@param config_root: path to read local config from (defaults to "/", see PORTAGE_CONFIGROOT)
+		@type config_root: String
+		@param target_root: __init__ override of $ROOT env variable.
+		@type target_root: String
+		@param local_config: Enables loading of local config (/etc/portage); used most by repoman to
+		ignore local config (keywording and unmasking)
+		@type local_config: Boolean
+		"""
+
+		debug = os.environ.get("PORTAGE_DEBUG") == "1"
+
+		self.already_in_regenerate = 0
+
+		self.locked   = 0
+		self.mycpv    = None
+		self.puse     = []
+		self.modifiedkeys = []
+		self.uvlist = []
+
+		self.virtuals = {}
+		self.virts_p = {}
+		self.dirVirtuals = None
+		self.v_count  = 0
+
+		# Virtuals obtained from the vartree
+		self.treeVirtuals = {}
+		# Virtuals by user specification. Includes negatives.
+		self.userVirtuals = {}
+		# Virtual negatives from user specifications.
+		self.negVirtuals  = {}
+
+		self.user_profile_dir = None
+		self.local_config = local_config
+
+		if clone:
+			self.incrementals = copy.deepcopy(clone.incrementals)
+			self.profile_path = copy.deepcopy(clone.profile_path)
+			self.user_profile_dir = copy.deepcopy(clone.user_profile_dir)
+			self.local_config = copy.deepcopy(clone.local_config)
+
+			self.module_priority = copy.deepcopy(clone.module_priority)
+			self.modules         = copy.deepcopy(clone.modules)
+
+			self.depcachedir = copy.deepcopy(clone.depcachedir)
+
+			self.packages = copy.deepcopy(clone.packages)
+			self.virtuals = copy.deepcopy(clone.virtuals)
+
+			self.treeVirtuals = copy.deepcopy(clone.treeVirtuals)
+			self.userVirtuals = copy.deepcopy(clone.userVirtuals)
+			self.negVirtuals  = copy.deepcopy(clone.negVirtuals)
+
+			self.use_defs = copy.deepcopy(clone.use_defs)
+			self.usemask  = copy.deepcopy(clone.usemask)
+			self.usemask_list = copy.deepcopy(clone.usemask_list)
+			self.pusemask_list = copy.deepcopy(clone.pusemask_list)
+			self.useforce      = copy.deepcopy(clone.useforce)
+			self.useforce_list = copy.deepcopy(clone.useforce_list)
+			self.puseforce_list = copy.deepcopy(clone.puseforce_list)
+			self.puse     = copy.deepcopy(clone.puse)
+			self.make_defaults_use = copy.deepcopy(clone.make_defaults_use)
+			self.pkgprofileuse = copy.deepcopy(clone.pkgprofileuse)
+			self.mycpv    = copy.deepcopy(clone.mycpv)
+
+			self.configlist = copy.deepcopy(clone.configlist)
+			self.lookuplist = self.configlist[:]
+			self.lookuplist.reverse()
+			self.configdict = {
+				"env.d":     self.configlist[0],
+				"pkginternal": self.configlist[1],
+				"globals":     self.configlist[2],
+				"defaults":    self.configlist[3],
+				"conf":        self.configlist[4],
+				"pkg":         self.configlist[5],
+				"auto":        self.configlist[6],
+				"backupenv":   self.configlist[7],
+				"env":         self.configlist[8] }
+			self.profiles = copy.deepcopy(clone.profiles)
+			self.backupenv  = self.configdict["backupenv"]
+			self.pusedict   = copy.deepcopy(clone.pusedict)
+			self.categories = copy.deepcopy(clone.categories)
+			self.pkeywordsdict = copy.deepcopy(clone.pkeywordsdict)
+			self.pmaskdict = copy.deepcopy(clone.pmaskdict)
+			self.punmaskdict = copy.deepcopy(clone.punmaskdict)
+			self.prevmaskdict = copy.deepcopy(clone.prevmaskdict)
+			self.pprovideddict = copy.deepcopy(clone.pprovideddict)
+			self.dirVirtuals = copy.deepcopy(clone.dirVirtuals)
+			self.treeVirtuals = copy.deepcopy(clone.treeVirtuals)
+			self.features = copy.deepcopy(clone.features)
+		else:
+
+			# backupenv is for calculated incremental variables.
+			self.backupenv = os.environ.copy()
+			if not local_config:
+				# Clean up pollution from portage_data so that it doesn't
+				# interfere with repoman.
+				self.backupenv.pop("USERLAND", None)
+
+			def check_var_directory(varname, var):
+				if not os.path.isdir(var):
+					writemsg(("!!! Error: %s='%s' is not a directory. " + \
+						"Please correct this.\n") % (varname, var),
+						noiselevel=-1)
+					raise portage_exception.DirectoryNotFound(var)
+
+			if config_root is None:
+				config_root = "/"
+
+			config_root = normalize_path(os.path.abspath(
+				config_root)).rstrip(os.path.sep) + os.path.sep
+
+			check_var_directory("PORTAGE_CONFIGROOT", config_root)
+
+			self.depcachedir = DEPCACHE_PATH
+
+			if not config_profile_path:
+				config_profile_path = \
+					os.path.join(config_root, PROFILE_PATH.lstrip(os.path.sep))
+				if os.path.isdir(config_profile_path):
+					self.profile_path = config_profile_path
+				else:
+					self.profile_path = None
+			else:
+				self.profile_path = config_profile_path[:]
+
+			if not config_incrementals:
+				writemsg("incrementals not specified to class config\n")
+				self.incrementals = copy.deepcopy(portage_const.INCREMENTALS)
+			else:
+				self.incrementals = copy.deepcopy(config_incrementals)
+
+			self.module_priority    = ["user","default"]
+			self.modules            = {}
+			self.modules["user"] = getconfig(
+				os.path.join(config_root, MODULES_FILE_PATH.lstrip(os.path.sep)))
+			if self.modules["user"] is None:
+				self.modules["user"] = {}
+			self.modules["default"] = {
+				"portdbapi.metadbmodule": "cache.metadata.database",
+				"portdbapi.auxdbmodule":  "cache.flat_hash.database",
+			}
+
+			self.usemask=[]
+			self.configlist=[]
+
+			# back up our incremental variables:
+			self.configdict={}
+			# configlist will contain: [ env.d, globals, defaults, conf, pkg, auto, backupenv, env ]
+			self.configlist.append({})
+			self.configdict["env.d"] = self.configlist[-1]
+
+			self.configlist.append({})
+			self.configdict["pkginternal"] = self.configlist[-1]
+
+			# The symlink might not exist or might not be a symlink.
+			if self.profile_path is None:
+				self.profiles = []
+			else:
+				self.profiles = []
+				def addProfile(currentPath):
+					parentsFile = os.path.join(currentPath, "parent")
+					if os.path.exists(parentsFile):
+						parents = grabfile(parentsFile)
+						if not parents:
+							raise portage_exception.ParseError(
+								"Empty parent file: '%s'" % parents_file)
+						for parentPath in parents:
+							parentPath = normalize_path(os.path.join(
+								currentPath, parentPath))
+							if os.path.exists(parentPath):
+								addProfile(parentPath)
+							else:
+								raise portage_exception.ParseError(
+									"Parent '%s' not found: '%s'" %  \
+									(parentPath, parentsFile))
+					self.profiles.append(currentPath)
+				addProfile(os.path.realpath(self.profile_path))
+			if local_config:
+				custom_prof = os.path.join(
+					config_root, CUSTOM_PROFILE_PATH.lstrip(os.path.sep))
+				if os.path.exists(custom_prof):
+					self.user_profile_dir = custom_prof
+					self.profiles.append(custom_prof)
+				del custom_prof
+
+			self.packages_list = [grabfile_package(os.path.join(x, "packages")) for x in self.profiles]
+			self.packages      = stack_lists(self.packages_list, incremental=1)
+			del self.packages_list
+			#self.packages = grab_stacked("packages", self.profiles, grabfile, incremental_lines=1)
+
+			# revmaskdict
+			self.prevmaskdict={}
+			for x in self.packages:
+				mycatpkg=dep_getkey(x)
+				if not self.prevmaskdict.has_key(mycatpkg):
+					self.prevmaskdict[mycatpkg]=[x]
+				else:
+					self.prevmaskdict[mycatpkg].append(x)
+
+			# get profile-masked use flags -- INCREMENTAL Child over parent
+			self.usemask_list = [grabfile(os.path.join(x, "use.mask")) \
+				for x in self.profiles]
+			self.usemask  = set(stack_lists(
+				self.usemask_list, incremental=True))
+			use_defs_lists = [grabdict(os.path.join(x, "use.defaults")) for x in self.profiles]
+			self.use_defs  = stack_dictlist(use_defs_lists, incremental=True)
+			del use_defs_lists
+
+			self.pusemask_list = []
+			rawpusemask = [grabdict_package(
+				os.path.join(x, "package.use.mask")) \
+				for x in self.profiles]
+			for i in xrange(len(self.profiles)):
+				cpdict = {}
+				for k, v in rawpusemask[i].iteritems():
+					cpdict.setdefault(dep_getkey(k), {})[k] = v
+				self.pusemask_list.append(cpdict)
+			del rawpusemask
+
+			self.pkgprofileuse = []
+			rawprofileuse = [grabdict_package(
+				os.path.join(x, "package.use"), juststrings=True) \
+				for x in self.profiles]
+			for i in xrange(len(self.profiles)):
+				cpdict = {}
+				for k, v in rawprofileuse[i].iteritems():
+					cpdict.setdefault(dep_getkey(k), {})[k] = v
+				self.pkgprofileuse.append(cpdict)
+			del rawprofileuse
+
+			self.useforce_list = [grabfile(os.path.join(x, "use.force")) \
+				for x in self.profiles]
+			self.useforce  = set(stack_lists(
+				self.useforce_list, incremental=True))
+
+			self.puseforce_list = []
+			rawpuseforce = [grabdict_package(
+				os.path.join(x, "package.use.force")) \
+				for x in self.profiles]
+			for i in xrange(len(self.profiles)):
+				cpdict = {}
+				for k, v in rawpuseforce[i].iteritems():
+					cpdict.setdefault(dep_getkey(k), {})[k] = v
+				self.puseforce_list.append(cpdict)
+			del rawpuseforce
+
+			try:
+				self.mygcfg   = getconfig(os.path.join(config_root, "etc", "make.globals"))
+
+				if self.mygcfg is None:
+					self.mygcfg = {}
+			except SystemExit, e:
+				raise
+			except Exception, e:
+				if debug:
+					raise
+				writemsg("!!! %s\n" % (e), noiselevel=-1)
+				if not isinstance(e, EnvironmentError):
+					writemsg("!!! Incorrect multiline literals can cause " + \
+						"this. Do not use them.\n", noiselevel=-1)
+				sys.exit(1)
+			self.configlist.append(self.mygcfg)
+			self.configdict["globals"]=self.configlist[-1]
+
+			self.make_defaults_use = []
+			self.mygcfg = {}
+			if self.profiles:
+				try:
+					mygcfg_dlists = [getconfig(os.path.join(x, "make.defaults")) for x in self.profiles]
+					for cfg in mygcfg_dlists:
+						if cfg:
+							self.make_defaults_use.append(cfg.get("USE", ""))
+						else:
+							self.make_defaults_use.append("")
+					self.mygcfg   = stack_dicts(mygcfg_dlists, incrementals=portage_const.INCREMENTALS, ignore_none=1)
+					#self.mygcfg = grab_stacked("make.defaults", self.profiles, getconfig)
+					if self.mygcfg is None:
+						self.mygcfg = {}
+				except SystemExit, e:
+					raise
+				except Exception, e:
+					if debug:
+						raise
+					writemsg("!!! %s\n" % (e), noiselevel=-1)
+					if not isinstance(e, EnvironmentError):
+						writemsg("!!! 'rm -Rf /usr/portage/profiles; " + \
+							"emerge sync' may fix this. If it does\n",
+							noiselevel=-1)
+						writemsg("!!! not then please report this to " + \
+							"bugs.gentoo.org and, if possible, a dev\n",
+								noiselevel=-1)
+						writemsg("!!! on #gentoo (irc.freenode.org)\n",
+							noiselevel=-1)
+					sys.exit(1)
+			self.configlist.append(self.mygcfg)
+			self.configdict["defaults"]=self.configlist[-1]
+
+			try:
+				self.mygcfg = getconfig(
+					os.path.join(config_root, MAKE_CONF_FILE.lstrip(os.path.sep)),
+					allow_sourcing=True)
+				if self.mygcfg is None:
+					self.mygcfg = {}
+			except SystemExit, e:
+				raise
+			except Exception, e:
+				if debug:
+					raise
+				writemsg("!!! %s\n" % (e), noiselevel=-1)
+				if not isinstance(e, EnvironmentError):
+					writemsg("!!! Incorrect multiline literals can cause " + \
+						"this. Do not use them.\n", noiselevel=-1)
+				sys.exit(1)
+
+			# Allow ROOT setting to come from make.conf if it's not overridden
+			# by the constructor argument (from the calling environment).  As a
+			# special exception for a very common use case, config_root == "/"
+			# implies that ROOT in make.conf should be ignored.  That way, the
+			# user can chroot into $ROOT and the ROOT setting in make.conf will
+			# be automatically ignored (unless config_root is other than "/").
+			if config_root != "/" and \
+				target_root is None and "ROOT" in self.mygcfg:
+				target_root = self.mygcfg["ROOT"]
+			
+			self.configlist.append(self.mygcfg)
+			self.configdict["conf"]=self.configlist[-1]
+
+			self.configlist.append({})
+			self.configdict["pkg"]=self.configlist[-1]
+
+			#auto-use:
+			self.configlist.append({})
+			self.configdict["auto"]=self.configlist[-1]
+
+			self.configlist.append(self.backupenv) # XXX Why though?
+			self.configdict["backupenv"]=self.configlist[-1]
+
+			self.configlist.append(os.environ.copy())
+			self.configdict["env"]=self.configlist[-1]
+			if not local_config:
+				# Clean up pollution from portage_data so that it doesn't
+				# interfere with repoman.
+				self.configdict["env"].pop("USERLAND", None)
+
+			# make lookuplist for loading package.*
+			self.lookuplist=self.configlist[:]
+			self.lookuplist.reverse()
+
+			# Blacklist vars that could interfere with portage internals.
+			for blacklisted in "CATEGORY", "PKGUSE", "PORTAGE_CONFIGROOT", \
+				"ROOT":
+				for cfg in self.lookuplist:
+					cfg.pop(blacklisted, None)
+			del blacklisted, cfg
+
+			if target_root is None:
+				target_root = "/"
+
+			target_root = normalize_path(os.path.abspath(
+				target_root)).rstrip(os.path.sep) + os.path.sep
+
+			check_var_directory("ROOT", target_root)
+
+			env_d = getconfig(
+				os.path.join(target_root, "etc", "profile.env"), expand=False)
+			# env_d will be None if profile.env doesn't exist.
+			if env_d:
+				self.configdict["env.d"].update(env_d)
+				# Remove duplicate values so they don't override updated
+				# profile.env values later (profile.env is reloaded in each
+				# call to self.regenerate).
+				for cfg in (self.configdict["backupenv"],
+					self.configdict["env"]):
+					for k, v in env_d.iteritems():
+						try:
+							if cfg[k] == v:
+								del cfg[k]
+						except KeyError:
+							pass
+				del cfg, k, v
+
+			self["PORTAGE_CONFIGROOT"] = config_root
+			self.backup_changes("PORTAGE_CONFIGROOT")
+			self["ROOT"] = target_root
+			self.backup_changes("ROOT")
+
+			self.pusedict = {}
+			self.pkeywordsdict = {}
+			self.punmaskdict = {}
+			abs_user_config = os.path.join(config_root,
+				USER_CONFIG_PATH.lstrip(os.path.sep))
+
+			# locations for "categories" and "arch.list" files
+			locations = [os.path.join(self["PORTDIR"], "profiles")]
+			pmask_locations = [os.path.join(self["PORTDIR"], "profiles")]
+			pmask_locations.extend(self.profiles)
+
+			""" repoman controls PORTDIR_OVERLAY via the environment, so no
+			special cases are needed here."""
+			overlay_profiles = []
+			for ov in self["PORTDIR_OVERLAY"].split():
+				ov = normalize_path(ov)
+				profiles_dir = os.path.join(ov, "profiles")
+				if os.path.isdir(profiles_dir):
+					overlay_profiles.append(profiles_dir)
+			locations += overlay_profiles
+			
+			pmask_locations.extend(overlay_profiles)
+
+			if local_config:
+				locations.append(abs_user_config)
+				pmask_locations.append(abs_user_config)
+				pusedict = grabdict_package(
+					os.path.join(abs_user_config, "package.use"), recursive=1)
+				for key in pusedict.keys():
+					cp = dep_getkey(key)
+					if not self.pusedict.has_key(cp):
+						self.pusedict[cp] = {}
+					self.pusedict[cp][key] = pusedict[key]
+
+				#package.keywords
+				pkgdict = grabdict_package(
+					os.path.join(abs_user_config, "package.keywords"),
+					recursive=1)
+				for key in pkgdict.keys():
+					# default to ~arch if no specific keyword is given
+					if not pkgdict[key]:
+						mykeywordlist = []
+						if self.configdict["defaults"] and self.configdict["defaults"].has_key("ACCEPT_KEYWORDS"):
+							groups = self.configdict["defaults"]["ACCEPT_KEYWORDS"].split()
+						else:
+							groups = []
+						for keyword in groups:
+							if not keyword[0] in "~-":
+								mykeywordlist.append("~"+keyword)
+						pkgdict[key] = mykeywordlist
+					cp = dep_getkey(key)
+					if not self.pkeywordsdict.has_key(cp):
+						self.pkeywordsdict[cp] = {}
+					self.pkeywordsdict[cp][key] = pkgdict[key]
+
+				#package.unmask
+				pkgunmasklines = grabfile_package(
+					os.path.join(abs_user_config, "package.unmask"),
+					recursive=1)
+				for x in pkgunmasklines:
+					mycatpkg=dep_getkey(x)
+					if self.punmaskdict.has_key(mycatpkg):
+						self.punmaskdict[mycatpkg].append(x)
+					else:
+						self.punmaskdict[mycatpkg]=[x]
+
+			#getting categories from an external file now
+			categories = [grabfile(os.path.join(x, "categories")) for x in locations]
+			self.categories = stack_lists(categories, incremental=1)
+			del categories
+
+			archlist = [grabfile(os.path.join(x, "arch.list")) for x in locations]
+			archlist = stack_lists(archlist, incremental=1)
+			self.configdict["conf"]["PORTAGE_ARCHLIST"] = " ".join(archlist)
+
+			#package.mask
+			pkgmasklines = []
+			for x in pmask_locations:
+				pkgmasklines.append(grabfile_package(
+					os.path.join(x, "package.mask"), recursive=1))
+			pkgmasklines = stack_lists(pkgmasklines, incremental=1)
+
+			self.pmaskdict = {}
+			for x in pkgmasklines:
+				mycatpkg=dep_getkey(x)
+				if self.pmaskdict.has_key(mycatpkg):
+					self.pmaskdict[mycatpkg].append(x)
+				else:
+					self.pmaskdict[mycatpkg]=[x]
+
+			pkgprovidedlines = [grabfile(os.path.join(x, "package.provided")) for x in self.profiles]
+			pkgprovidedlines = stack_lists(pkgprovidedlines, incremental=1)
+			has_invalid_data = False
+			for x in range(len(pkgprovidedlines)-1, -1, -1):
+				myline = pkgprovidedlines[x]
+				if not isvalidatom("=" + myline):
+					writemsg("Invalid package name in package.provided:" + \
+						" %s\n" % myline, noiselevel=-1)
+					has_invalid_data = True
+					del pkgprovidedlines[x]
+					continue
+				cpvr = catpkgsplit(pkgprovidedlines[x])
+				if not cpvr or cpvr[0] == "null":
+					writemsg("Invalid package name in package.provided: "+pkgprovidedlines[x]+"\n",
+						noiselevel=-1)
+					has_invalid_data = True
+					del pkgprovidedlines[x]
+					continue
+				if cpvr[0] == "virtual":
+					writemsg("Virtual package in package.provided: %s\n" % \
+						myline, noiselevel=-1)
+					has_invalid_data = True
+					del pkgprovidedlines[x]
+					continue
+			if has_invalid_data:
+				writemsg("See portage(5) for correct package.provided usage.\n",
+					noiselevel=-1)
+			self.pprovideddict = {}
+			for x in pkgprovidedlines:
+				cpv=catpkgsplit(x)
+				if not x:
+					continue
+				mycatpkg=dep_getkey(x)
+				if self.pprovideddict.has_key(mycatpkg):
+					self.pprovideddict[mycatpkg].append(x)
+				else:
+					self.pprovideddict[mycatpkg]=[x]
+
+			# reasonable defaults; this is important as without USE_ORDER,
+			# USE will always be "" (nothing set)!
+			if "USE_ORDER" not in self:
+				self.backupenv["USE_ORDER"] = "env:pkg:conf:defaults:pkginternal"
+
+			self["PORTAGE_GID"] = str(portage_gid)
+			self.backup_changes("PORTAGE_GID")
+
+			if self.get("PORTAGE_DEPCACHEDIR", None):
+				self.depcachedir = self["PORTAGE_DEPCACHEDIR"]
+			self["PORTAGE_DEPCACHEDIR"] = self.depcachedir
+			self.backup_changes("PORTAGE_DEPCACHEDIR")
+
+			overlays = self.get("PORTDIR_OVERLAY","").split()
+			if overlays:
+				new_ov = []
+				for ov in overlays:
+					ov = normalize_path(ov)
+					if os.path.isdir(ov):
+						new_ov.append(ov)
+					else:
+						writemsg("!!! Invalid PORTDIR_OVERLAY" + \
+							" (not a dir): '%s'\n" % ov, noiselevel=-1)
+				self["PORTDIR_OVERLAY"] = " ".join(new_ov)
+				self.backup_changes("PORTDIR_OVERLAY")
+
+			if "CBUILD" not in self and "CHOST" in self:
+				self["CBUILD"] = self["CHOST"]
+				self.backup_changes("CBUILD")
+
+			self["PORTAGE_BIN_PATH"] = PORTAGE_BIN_PATH
+			self.backup_changes("PORTAGE_BIN_PATH")
+			self["PORTAGE_PYM_PATH"] = PORTAGE_PYM_PATH
+			self.backup_changes("PORTAGE_PYM_PATH")
+
+			for var in ("PORTAGE_INST_UID", "PORTAGE_INST_GID"):
+				try:
+					self[var] = str(int(self.get(var, "0")))
+				except ValueError:
+					writemsg(("!!! %s='%s' is not a valid integer.  " + \
+						"Falling back to '0'.\n") % (var, self[var]),
+						noiselevel=-1)
+					self[var] = "0"
+				self.backup_changes(var)
+
+			self.regenerate()
+			self.features = portage_util.unique_array(self["FEATURES"].split())
+
+			if "gpg" in self.features:
+				if not os.path.exists(self["PORTAGE_GPG_DIR"]) or \
+					not os.path.isdir(self["PORTAGE_GPG_DIR"]):
+					writemsg(colorize("BAD", "PORTAGE_GPG_DIR is invalid." + \
+						" Removing gpg from FEATURES.\n"), noiselevel=-1)
+					self.features.remove("gpg")
+
+			if not portage_exec.sandbox_capable and \
+				("sandbox" in self.features or "usersandbox" in self.features):
+				if self.profile_path is not None and \
+					os.path.realpath(self.profile_path) == \
+					os.path.realpath(PROFILE_PATH):
+					""" Don't show this warning when running repoman and the
+					sandbox feature came from a profile that doesn't belong to
+					the user."""
+					writemsg(colorize("BAD", "!!! Problem with sandbox" + \
+						" binary. Disabling...\n\n"), noiselevel=-1)
+				if "sandbox" in self.features:
+					self.features.remove("sandbox")
+				if "usersandbox" in self.features:
+					self.features.remove("usersandbox")
+
+			self.features.sort()
+			self["FEATURES"] = " ".join(self.features)
+			self.backup_changes("FEATURES")
+
+			self._init_dirs()
+
+		if mycpv:
+			self.setcpv(mycpv)
+
+	def _init_dirs(self):
+		"""
+		Create a few directories that are critical to portage operation
+		"""
+		if not os.access(self["ROOT"], os.W_OK):
+			return
+
+		dir_mode_map = {
+			"tmp"             :(-1,          01777, 0),
+			"var/tmp"         :(-1,          01777, 0),
+			"var/lib/portage" :(portage_gid, 02750, 02),
+			"var/cache/edb"   :(portage_gid,  0755, 02)
+		}
+
+		for mypath, (gid, mode, modemask) in dir_mode_map.iteritems():
+			try:
+				mydir = os.path.join(self["ROOT"], mypath)
+				portage_util.ensure_dirs(mydir, gid=gid, mode=mode, mask=modemask)
+			except portage_exception.PortageException, e:
+				writemsg("!!! Directory initialization failed: '%s'\n" % mydir,
+					noiselevel=-1)
+				writemsg("!!! %s\n" % str(e),
+					noiselevel=-1)
+
+	def validate(self):
+		"""Validate miscellaneous settings and display warnings if necessary.
+		(This code was previously in the global scope of portage.py)"""
+
+		groups = self["ACCEPT_KEYWORDS"].split()
+		archlist = self.archlist()
+		if not archlist:
+			writemsg("--- 'profiles/arch.list' is empty or not available. Empty portage tree?\n")
+		else:
+			for group in groups:
+				if group not in archlist and group[0] != '-':
+					writemsg("!!! INVALID ACCEPT_KEYWORDS: %s\n" % str(group),
+						noiselevel=-1)
+
+		abs_profile_path = os.path.join(self["PORTAGE_CONFIGROOT"],
+			PROFILE_PATH.lstrip(os.path.sep))
+		if not os.path.islink(abs_profile_path) and \
+			not os.path.exists(os.path.join(abs_profile_path, "parent")) and \
+			os.path.exists(os.path.join(self["PORTDIR"], "profiles")):
+			writemsg("\a\n\n!!! %s is not a symlink and will probably prevent most merges.\n" % abs_profile_path,
+				noiselevel=-1)
+			writemsg("!!! It should point into a profile within %s/profiles/\n" % self["PORTDIR"])
+			writemsg("!!! (You can safely ignore this message when syncing. It's harmless.)\n\n\n")
+
+		abs_user_virtuals = os.path.join(self["PORTAGE_CONFIGROOT"],
+			USER_VIRTUALS_FILE.lstrip(os.path.sep))
+		if os.path.exists(abs_user_virtuals):
+			writemsg("\n!!! /etc/portage/virtuals is deprecated in favor of\n")
+			writemsg("!!! /etc/portage/profile/virtuals. Please move it to\n")
+			writemsg("!!! this new location.\n\n")
+
+	def loadVirtuals(self,root):
+		"""Not currently used by portage."""
+		writemsg("DEPRECATED: portage.config.loadVirtuals\n")
+		self.getvirtuals(root)
+
+	def load_best_module(self,property_string):
+		best_mod = best_from_dict(property_string,self.modules,self.module_priority)
+		try:
+			mod = load_mod(best_mod)
+		except ImportError:
+			dump_traceback(red("Error: Failed to import module '%s'") % best_mod, noiselevel=0)
+			sys.exit(1)
+		return mod
+
+	def lock(self):
+		self.locked = 1
+
+	def unlock(self):
+		self.locked = 0
+
+	def modifying(self):
+		if self.locked:
+			raise Exception, "Configuration is locked."
+
+	def backup_changes(self,key=None):
+		self.modifying()
+		if key and self.configdict["env"].has_key(key):
+			self.backupenv[key] = copy.deepcopy(self.configdict["env"][key])
+		else:
+			raise KeyError, "No such key defined in environment: %s" % key
+
+	def reset(self,keeping_pkg=0,use_cache=1):
+		"""
+		Restore environment from self.backupenv, call self.regenerate()
+		@param keeping_pkg: Should we keep the set_cpv() data or delete it.
+		@type keeping_pkg: Boolean
+		@param use_cache: Should self.regenerate use the cache or not
+		@type use_cache: Boolean
+		@rype: None
+		"""
+		self.modifying()
+		self.configdict["env"].clear()
+		self.configdict["env"].update(self.backupenv)
+
+		self.modifiedkeys = []
+		if not keeping_pkg:
+			self.mycpv = None
+			self.puse = ""
+			self.configdict["pkg"].clear()
+			self.configdict["pkginternal"].clear()
+			self.configdict["defaults"]["USE"] = \
+				" ".join(self.make_defaults_use)
+			self.usemask  = set(stack_lists(
+				self.usemask_list, incremental=True))
+			self.useforce  = set(stack_lists(
+				self.useforce_list, incremental=True))
+		self.regenerate(use_cache=use_cache)
+
+	def load_infodir(self,infodir):
+		self.modifying()
+		if self.configdict.has_key("pkg"):
+			for x in self.configdict["pkg"].keys():
+				del self.configdict["pkg"][x]
+		else:
+			writemsg("No pkg setup for settings instance?\n",
+				noiselevel=-1)
+			sys.exit(17)
+
+		if os.path.exists(infodir):
+			if os.path.exists(infodir+"/environment"):
+				self.configdict["pkg"]["PORT_ENV_FILE"] = infodir+"/environment"
+
+			myre = re.compile('^[A-Z]+$')
+			null_byte = "\0"
+			for filename in listdir(infodir,filesonly=1,EmptyOnError=1):
+				if filename == "FEATURES":
+					# FEATURES from the build host shouldn't be interpreted as
+					# FEATURES on the client system.
+					continue
+				if myre.match(filename):
+					try:
+						file_path = os.path.join(infodir, filename)
+						mydata = open(file_path).read().strip()
+						if len(mydata) < 2048 or filename == "USE":
+							if null_byte in mydata:
+								writemsg("!!! Null byte found in metadata " + \
+									"file: '%s'\n" % file_path, noiselevel=-1)
+								continue
+							if filename == "USE":
+								binpkg_flags = "-* " + mydata
+								self.configdict["pkg"][filename] = binpkg_flags
+								self.configdict["env"][filename] = mydata
+							else:
+								self.configdict["pkg"][filename] = mydata
+								self.configdict["env"][filename] = mydata
+						# CATEGORY is important because it's used in doebuild
+						# to infer the cpv.  If it's corrupted, it leads to
+						# strange errors later on, so we'll validate it and
+						# print a warning if necessary.
+						if filename == "CATEGORY":
+							matchobj = re.match("[-a-zA-Z0-9_.+]+", mydata)
+							if not matchobj or matchobj.start() != 0 or \
+								matchobj.end() != len(mydata):
+								writemsg("!!! CATEGORY file is corrupt: %s\n" % \
+									os.path.join(infodir, filename), noiselevel=-1)
+					except (OSError, IOError):
+						writemsg("!!! Unable to read file: %s\n" % infodir+"/"+filename,
+							noiselevel=-1)
+						pass
+			return 1
+		return 0
+
+	def setcpv(self, mycpv, use_cache=1, mydb=None):
+		"""
+		Load a particular CPV into the config, this lets us see the
+		Default USE flags for a particular ebuild as well as the USE
+		flags from package.use.
+
+		@param mycpv: A cpv to load
+		@type mycpv: string
+		@param use_cache: Enables caching
+		@type use_cache: Boolean
+		@param mydb: a dbapi instance that supports aux_get with the IUSE key.
+		@type mydb: dbapi or derivative.
+		@rtype: None
+		"""
+
+		self.modifying()
+		if self.mycpv == mycpv:
+			return
+		has_changed = False
+		self.mycpv = mycpv
+		cp = dep_getkey(mycpv)
+		pkginternaluse = ""
+		if mydb:
+			pkginternaluse = " ".join([x[1:] \
+				for x in mydb.aux_get(mycpv, ["IUSE"])[0].split() \
+				if x.startswith("+")])
+		if pkginternaluse != self.configdict["pkginternal"].get("USE", ""):
+			self.configdict["pkginternal"]["USE"] = pkginternaluse
+			has_changed = True
+		defaults = []
+		for i in xrange(len(self.profiles)):
+			defaults.append(self.make_defaults_use[i])
+			cpdict = self.pkgprofileuse[i].get(cp, None)
+			if cpdict:
+				best_match = best_match_to_list(self.mycpv, cpdict.keys())
+				if best_match:
+					defaults.append(cpdict[best_match])
+		defaults = " ".join(defaults)
+		if defaults != self.configdict["defaults"].get("USE",""):
+			self.configdict["defaults"]["USE"] = defaults
+			has_changed = True
+		useforce = []
+		for i in xrange(len(self.profiles)):
+			useforce.append(self.useforce_list[i])
+			cpdict = self.puseforce_list[i].get(cp, None)
+			if cpdict:
+				best_match = best_match_to_list(self.mycpv, cpdict.keys())
+				if best_match:
+					useforce.append(cpdict[best_match])
+		useforce = set(stack_lists(useforce, incremental=True))
+		if useforce != self.useforce:
+			self.useforce = useforce
+			has_changed = True
+		usemask = []
+		for i in xrange(len(self.profiles)):
+			usemask.append(self.usemask_list[i])
+			cpdict = self.pusemask_list[i].get(cp, None)
+			if cpdict:
+				best_match = best_match_to_list(self.mycpv, cpdict.keys())
+				if best_match:
+					usemask.append(cpdict[best_match])
+		usemask = set(stack_lists(usemask, incremental=True))
+		if usemask != self.usemask:
+			self.usemask = usemask
+			has_changed = True
+		oldpuse = self.puse
+		self.puse = ""
+		if self.pusedict.has_key(cp):
+			self.pusekey = best_match_to_list(self.mycpv, self.pusedict[cp].keys())
+			if self.pusekey:
+				self.puse = " ".join(self.pusedict[cp][self.pusekey])
+		if oldpuse != self.puse:
+			has_changed = True
+		self.configdict["pkg"]["PKGUSE"] = self.puse[:] # For saving to PUSE file
+		self.configdict["pkg"]["USE"]    = self.puse[:] # this gets appended to USE
+		# CATEGORY is essential for doebuild calls
+		self.configdict["pkg"]["CATEGORY"] = mycpv.split("/")[0]
+		if has_changed:
+			self.reset(keeping_pkg=1,use_cache=use_cache)
+
+	def setinst(self,mycpv,mydbapi):
+		self.modifying()
+		if len(self.virtuals) == 0:
+			self.getvirtuals()
+		# Grab the virtuals this package provides and add them into the tree virtuals.
+		provides = mydbapi.aux_get(mycpv, ["PROVIDE"])[0]
+		if isinstance(mydbapi, portdbapi):
+			myuse = self["USE"]
+		else:
+			myuse = mydbapi.aux_get(mycpv, ["USE"])[0]
+		virts = flatten(portage_dep.use_reduce(portage_dep.paren_reduce(provides), uselist=myuse.split()))
+
+		cp = dep_getkey(mycpv)
+		for virt in virts:
+			virt = dep_getkey(virt)
+			if not self.treeVirtuals.has_key(virt):
+				self.treeVirtuals[virt] = []
+			# XXX: Is this bad? -- It's a permanent modification
+			if cp not in self.treeVirtuals[virt]:
+				self.treeVirtuals[virt].append(cp)
+
+		self.virtuals = self.__getvirtuals_compile()
+
+
+	def regenerate(self,useonly=0,use_cache=1):
+		"""
+		Regenerate settings
+		This involves regenerating valid USE flags, re-expanding USE_EXPAND flags
+		re-stacking USE flags (-flag and -*), as well as any other INCREMENTAL
+		variables.  This also updates the env.d configdict; useful in case an ebuild
+		changes the environment.
+
+		If FEATURES has already stacked, it is not stacked twice.
+
+		@param useonly: Only regenerate USE flags (not any other incrementals)
+		@type useonly: Boolean
+		@param use_cache: Enable Caching (only for autouse)
+		@type use_cache: Boolean
+		@rtype: None
+		"""
+
+		self.modifying()
+		if self.already_in_regenerate:
+			# XXX: THIS REALLY NEEDS TO GET FIXED. autouse() loops.
+			writemsg("!!! Looping in regenerate.\n",1)
+			return
+		else:
+			self.already_in_regenerate = 1
+
+		# We grab the latest profile.env here since it changes frequently.
+		self.configdict["env.d"].clear()
+		env_d = getconfig(
+			os.path.join(self["ROOT"], "etc", "profile.env"), expand=False)
+		if env_d:
+			# env_d will be None if profile.env doesn't exist.
+			self.configdict["env.d"].update(env_d)
+
+		if useonly:
+			myincrementals=["USE"]
+		else:
+			myincrementals = self.incrementals
+		myincrementals = set(myincrementals)
+		# If self.features exists, it has already been stacked and may have
+		# been mutated, so don't stack it again or else any mutations will be
+		# reverted.
+		if "FEATURES" in myincrementals and hasattr(self, "features"):
+			myincrementals.remove("FEATURES")
+
+		if "USE" in myincrementals:
+			# Process USE last because it depends on USE_EXPAND which is also
+			# an incremental!
+			myincrementals.remove("USE")
+
+		for mykey in myincrementals:
+
+			mydbs=self.configlist[:-1]
+
+			myflags=[]
+			for curdb in mydbs:
+				if mykey not in curdb:
+					continue
+				#variables are already expanded
+				mysplit = curdb[mykey].split()
+
+				for x in mysplit:
+					if x=="-*":
+						# "-*" is a special "minus" var that means "unset all settings".
+						# so USE="-* gnome" will have *just* gnome enabled.
+						myflags = []
+						continue
+
+					if x[0]=="+":
+						# Not legal. People assume too much. Complain.
+						writemsg(red("USE flags should not start with a '+': %s\n" % x),
+							noiselevel=-1)
+						x=x[1:]
+						if not x:
+							continue
+
+					if (x[0]=="-"):
+						if (x[1:] in myflags):
+							# Unset/Remove it.
+							del myflags[myflags.index(x[1:])]
+						continue
+
+					# We got here, so add it now.
+					if x not in myflags:
+						myflags.append(x)
+
+			myflags.sort()
+			#store setting in last element of configlist, the original environment:
+			if myflags or mykey in self:
+				self.configlist[-1][mykey] = " ".join(myflags)
+			del myflags
+
+		# Do the USE calculation last because it depends on USE_EXPAND.
+		if "auto" in self["USE_ORDER"].split(":"):
+			self.configdict["auto"]["USE"] = autouse(
+				vartree(root=self["ROOT"], categories=self.categories,
+					settings=self),
+				use_cache=use_cache, mysettings=self)
+		else:
+			self.configdict["auto"]["USE"] = ""
+
+		use_expand_protected = []
+		use_expand = self.get("USE_EXPAND", "").split()
+		for var in use_expand:
+			var_lower = var.lower()
+			for x in self.get(var, "").split():
+				# Any incremental USE_EXPAND variables have already been
+				# processed, so leading +/- operators are invalid here.
+				if x[0] == "+":
+					writemsg(colorize("BAD", "Invalid '+' operator in " + \
+						"non-incremental variable '%s': '%s'\n" % (var, x)),
+						noiselevel=-1)
+					x = x[1:]
+				if x[0] == "-":
+					writemsg(colorize("BAD", "Invalid '-' operator in " + \
+						"non-incremental variable '%s': '%s'\n" % (var, x)),
+						noiselevel=-1)
+					continue
+				mystr = var_lower + "_" + x
+				if mystr not in use_expand_protected:
+					use_expand_protected.append(mystr)
+
+		if not self.uvlist:
+			for x in self["USE_ORDER"].split(":"):
+				if x in self.configdict:
+					self.uvlist.append(self.configdict[x])
+			self.uvlist.reverse()
+
+		myflags = use_expand_protected[:]
+		for curdb in self.uvlist:
+			if "USE" not in curdb:
+				continue
+			mysplit = curdb["USE"].split()
+			for x in mysplit:
+				if x == "-*":
+					myflags = use_expand_protected[:]
+					continue
+
+				if x[0] == "+":
+					writemsg(colorize("BAD", "USE flags should not start " + \
+						"with a '+': %s\n" % x), noiselevel=-1)
+					x = x[1:]
+					if not x:
+						continue
+
+				if x[0] == "-":
+					try:
+						myflags.remove(x[1:])
+					except ValueError:
+						pass
+					continue
+
+				if x not in myflags:
+					myflags.append(x)
+
+		myflags = set(myflags)
+		myflags.update(self.useforce)
+
+		# FEATURES=test should imply USE=test
+		if "test" in self.configlist[-1].get("FEATURES","").split():
+			myflags.add("test")
+
+		usesplit = [ x for x in myflags if \
+			x not in self.usemask]
+
+		usesplit.sort()
+
+		# Use the calculated USE flags to regenerate the USE_EXPAND flags so
+		# that they are consistent.
+		for var in use_expand:
+			prefix = var.lower() + "_"
+			prefix_len = len(prefix)
+			expand_flags = set([ x[prefix_len:] for x in usesplit \
+				if x.startswith(prefix) ])
+			var_split = self.get(var, "").split()
+			# Preserve the order of var_split because it can matter for things
+			# like LINGUAS.
+			var_split = [ x for x in var_split if x in expand_flags ]
+			var_split.extend(expand_flags.difference(var_split))
+			if var_split or var in self:
+				# Don't export empty USE_EXPAND vars unless the user config
+				# exports them as empty.  This is required for vars such as
+				# LINGUAS, where unset and empty have different meanings.
+				self[var] = " ".join(var_split)
+
+		# Pre-Pend ARCH variable to USE settings so '-*' in env doesn't kill arch.
+		if self.configdict["defaults"].has_key("ARCH"):
+			if self.configdict["defaults"]["ARCH"]:
+				if self.configdict["defaults"]["ARCH"] not in usesplit:
+					usesplit.insert(0,self.configdict["defaults"]["ARCH"])
+
+		self.configlist[-1]["USE"]= " ".join(usesplit)
+
+		self.already_in_regenerate = 0
+
+	def get_virts_p(self, myroot):
+		if self.virts_p:
+			return self.virts_p
+		virts = self.getvirtuals(myroot)
+		if virts:
+			myvkeys = virts.keys()
+			for x in myvkeys:
+				vkeysplit = x.split("/")
+				if not self.virts_p.has_key(vkeysplit[1]):
+					self.virts_p[vkeysplit[1]] = virts[x]
+		return self.virts_p
+
+	def getvirtuals(self, myroot=None):
+		"""myroot is now ignored because, due to caching, it has always been
+		broken for all but the first call."""
+		myroot = self["ROOT"]
+		if self.virtuals:
+			return self.virtuals
+
+		virtuals_list = []
+		for x in self.profiles:
+			virtuals_file = os.path.join(x, "virtuals")
+			virtuals_dict = grabdict(virtuals_file)
+			for k in virtuals_dict.keys():
+				if not isvalidatom(k) or dep_getkey(k) != k:
+					writemsg("--- Invalid virtuals atom in %s: %s\n" % \
+						(virtuals_file, k), noiselevel=-1)
+					del virtuals_dict[k]
+					continue
+				myvalues = virtuals_dict[k]
+				for x in myvalues:
+					myatom = x
+					if x.startswith("-"):
+						# allow incrementals
+						myatom = x[1:]
+					if not isvalidatom(myatom):
+						writemsg("--- Invalid atom in %s: %s\n" % \
+							(virtuals_file, x), noiselevel=-1)
+						myvalues.remove(x)
+				if not myvalues:
+					del virtuals_dict[k]
+			if virtuals_dict:
+				virtuals_list.append(virtuals_dict)
+
+		self.dirVirtuals = stack_dictlist(virtuals_list, incremental=True)
+		del virtuals_list
+
+		for virt in self.dirVirtuals:
+			# Preference for virtuals decreases from left to right.
+			self.dirVirtuals[virt].reverse()
+
+		# Repoman does not use user or tree virtuals.
+		if self.local_config and not self.treeVirtuals:
+			temp_vartree = vartree(myroot, None,
+				categories=self.categories, settings=self)
+			# Reduce the provides into a list by CP.
+			self.treeVirtuals = map_dictlist_vals(getCPFromCPV,temp_vartree.get_all_provides())
+
+		self.virtuals = self.__getvirtuals_compile()
+		return self.virtuals
+
+	def __getvirtuals_compile(self):
+		"""Stack installed and profile virtuals.  Preference for virtuals
+		decreases from left to right.
+		Order of preference:
+		1. installed and in profile
+		2. installed only
+		3. profile only
+		"""
+
+		# Virtuals by profile+tree preferences.
+		ptVirtuals   = {}
+
+		for virt, installed_list in self.treeVirtuals.iteritems():
+			profile_list = self.dirVirtuals.get(virt, None)
+			if not profile_list:
+				continue
+			for cp in installed_list:
+				if cp in profile_list:
+					ptVirtuals.setdefault(virt, [])
+					ptVirtuals[virt].append(cp)
+
+		virtuals = stack_dictlist([ptVirtuals, self.treeVirtuals,
+			self.dirVirtuals])
+		return virtuals
+
+	def __delitem__(self,mykey):
+		self.modifying()
+		for x in self.lookuplist:
+			if x != None:
+				if mykey in x:
+					del x[mykey]
+
+	def __getitem__(self,mykey):
+		match = ''
+		for x in self.lookuplist:
+			if x is None:
+				writemsg("!!! lookuplist is null.\n")
+			elif x.has_key(mykey):
+				match = x[mykey]
+				break
+		return match
+
+	def has_key(self,mykey):
+		for x in self.lookuplist:
+			if x.has_key(mykey):
+				return 1
+		return 0
+
+	def __contains__(self, mykey):
+		"""Called to implement membership test operators (in and not in)."""
+		return bool(self.has_key(mykey))
+
+	def setdefault(self, k, x=None):
+		if k in self:
+			return self[k]
+		else:
+			self[k] = x
+			return x
+
+	def get(self, k, x=None):
+		if k in self:
+			return self[k]
+		else:
+			return x
+
+	def keys(self):
+		return unique_array(flatten([x.keys() for x in self.lookuplist]))
+
+	def __setitem__(self,mykey,myvalue):
+		"set a value; will be thrown away at reset() time"
+		if type(myvalue) != types.StringType:
+			raise ValueError("Invalid type being used as a value: '%s': '%s'" % (str(mykey),str(myvalue)))
+		self.modifying()
+		self.modifiedkeys += [mykey]
+		self.configdict["env"][mykey]=myvalue
+
+	def environ(self):
+		"return our locally-maintained environment"
+		mydict={}
+		for x in self.keys():
+			myvalue = self[x]
+			if not isinstance(myvalue, basestring):
+				writemsg("!!! Non-string value in config: %s=%s\n" % \
+					(x, myvalue), noiselevel=-1)
+				continue
+			mydict[x] = myvalue
+		if not mydict.has_key("HOME") and mydict.has_key("BUILD_PREFIX"):
+			writemsg("*** HOME not set. Setting to "+mydict["BUILD_PREFIX"]+"\n")
+			mydict["HOME"]=mydict["BUILD_PREFIX"][:]
+
+		return mydict
+
+	def thirdpartymirrors(self):
+		if getattr(self, "_thirdpartymirrors", None) is None:
+			profileroots = [os.path.join(self["PORTDIR"], "profiles")]
+			for x in self["PORTDIR_OVERLAY"].split():
+				profileroots.insert(0, os.path.join(x, "profiles"))
+			thirdparty_lists = [grabdict(os.path.join(x, "thirdpartymirrors")) for x in profileroots]
+			self._thirdpartymirrors = stack_dictlist(thirdparty_lists, incremental=True)
+		return self._thirdpartymirrors
+
+	def archlist(self):
+		return flatten([[myarch, "~" + myarch] \
+			for myarch in self["PORTAGE_ARCHLIST"].split()])
+
+	def selinux_enabled(self):
+		if getattr(self, "_selinux_enabled", None) is None:
+			self._selinux_enabled = 0
+			if "selinux" in self["USE"].split():
+				if "selinux" in globals():
+					if selinux.is_selinux_enabled() == 1:
+						self._selinux_enabled = 1
+					else:
+						self._selinux_enabled = 0
+				else:
+					writemsg("!!! SELinux module not found. Please verify that it was installed.\n",
+						noiselevel=-1)
+					self._selinux_enabled = 0
+			if self._selinux_enabled == 0:
+				try:	
+					del sys.modules["selinux"]
+				except KeyError:
+					pass
+		return self._selinux_enabled
+
+# XXX This would be to replace getstatusoutput completely.
+# XXX Issue: cannot block execution. Deadlock condition.
+def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, **keywords):
+	"""
+	Spawn a subprocess with extra portage-specific options.
+	Optiosn include:
+
+	Sandbox: Sandbox means the spawned process will be limited in its ability t
+	read and write files (normally this means it is restricted to ${IMAGE}/)
+	SElinux Sandbox: Enables sandboxing on SElinux
+	Reduced Privileges: Drops privilages such that the process runs as portage:portage
+	instead of as root.
+
+	Notes: os.system cannot be used because it messes with signal handling.  Instead we
+	use the portage_exec spawn* family of functions.
+
+	This function waits for the process to terminate.
+
+	@param mystring: Command to run
+	@type mystring: String
+	@param mysettings: Either a Dict of Key,Value pairs or an instance of portage.config
+	@type mysettings: Dictionary or config instance
+	@param debug: Ignored
+	@type debug: Boolean
+	@param free: Enable sandboxing for this process
+	@type free: Boolean
+	@param droppriv: Drop to portage:portage when running this command
+	@type droppriv: Boolean
+	@param sesandbox: Enable SELinux Sandboxing (toggles a context switch)
+	@type sesandbox: Boolean
+	@param keywords: Extra options encoded as a dict, to be passed to spawn
+	@type keywords: Dictionary
+	@rtype: Integer
+	@returns:
+	1. The return code of the spawned process.
+	"""
+
+	if type(mysettings) == types.DictType:
+		env=mysettings
+		keywords["opt_name"]="[ %s ]" % "portage"
+	else:
+		check_config_instance(mysettings)
+		env=mysettings.environ()
+		keywords["opt_name"]="[%s]" % mysettings["PF"]
+
+	# The default policy for the sesandbox domain only allows entry (via exec)
+	# from shells and from binaries that belong to portage (the number of entry
+	# points is minimized).  The "tee" binary is not among the allowed entry
+	# points, so it is spawned outside of the sesandbox domain and reads from a
+	# pipe between two domains.
+	logfile = keywords.get("logfile")
+	mypids = []
+	pw = None
+	if logfile:
+		del keywords["logfile"]
+		fd_pipes = keywords.get("fd_pipes")
+		if fd_pipes is None:
+			fd_pipes = {0:0, 1:1, 2:2}
+		elif 1 not in fd_pipes or 2 not in fd_pipes:
+			raise ValueError(fd_pipes)
+		pr, pw = os.pipe()
+		mypids.extend(portage_exec.spawn(('tee', '-i', '-a', logfile),
+			 returnpid=True, fd_pipes={0:pr, 1:fd_pipes[1], 2:fd_pipes[2]}))
+		os.close(pr)
+		fd_pipes[1] = pw
+		fd_pipes[2] = pw
+		keywords["fd_pipes"] = fd_pipes
+
+	features = mysettings.features
+	# XXX: Negative RESTRICT word
+	droppriv=(droppriv and ("userpriv" in features) and not \
+		(("nouserpriv" in mysettings["RESTRICT"].split()) or \
+		 ("userpriv" in mysettings["RESTRICT"].split())))
+
+	if droppriv and not uid and portage_gid and portage_uid:
+		keywords.update({"uid":portage_uid,"gid":portage_gid,"groups":userpriv_groups,"umask":002})
+
+	if not free:
+		free=((droppriv and "usersandbox" not in features) or \
+			(not droppriv and "sandbox" not in features and "usersandbox" not in features))
+
+	if free:
+		keywords["opt_name"] += " bash"
+		spawn_func = portage_exec.spawn_bash
+	else:
+		keywords["opt_name"] += " sandbox"
+		spawn_func = portage_exec.spawn_sandbox
+
+	if sesandbox:
+		con = selinux.getcontext()
+		con = con.replace(mysettings["PORTAGE_T"], mysettings["PORTAGE_SANDBOX_T"])
+		selinux.setexec(con)
+
+	returnpid = keywords.get("returnpid")
+	keywords["returnpid"] = True
+	try:
+		mypids.extend(spawn_func(mystring, env=env, **keywords))
+	finally:
+		if pw:
+			os.close(pw)
+		if sesandbox:
+			selinux.setexec(None)
+
+	if returnpid:
+		return mypids
+
+	while mypids:
+		pid = mypids.pop(0)
+		retval = os.waitpid(pid, 0)[1]
+		portage_exec.spawned_pids.remove(pid)
+		if retval != os.EX_OK:
+			for pid in mypids:
+				if os.waitpid(pid, os.WNOHANG) == (0,0):
+					import signal
+					os.kill(pid, signal.SIGTERM)
+					os.waitpid(pid, 0)
+				portage_exec.spawned_pids.remove(pid)
+			if retval & 0xff:
+				return (retval & 0xff) << 8
+			return retval >> 8
+	return os.EX_OK
+
+def fetch(myuris, mysettings, listonly=0, fetchonly=0, locks_in_subdir=".locks",use_locks=1, try_mirrors=1):
+	"fetch files.  Will use digest file if available."
+
+	features = mysettings.features
+	# 'nomirror' is bad/negative logic. You Restrict mirroring, not no-mirroring.
+	if ("mirror" in mysettings["RESTRICT"].split()) or \
+	   ("nomirror" in mysettings["RESTRICT"].split()):
+		if ("mirror" in features) and ("lmirror" not in features):
+			# lmirror should allow you to bypass mirror restrictions.
+			# XXX: This is not a good thing, and is temporary at best.
+			print ">>> \"mirror\" mode desired and \"mirror\" restriction found; skipping fetch."
+			return 1
+
+	thirdpartymirrors = mysettings.thirdpartymirrors()
+
+	check_config_instance(mysettings)
+
+	custommirrors = grabdict(os.path.join(mysettings["PORTAGE_CONFIGROOT"],
+		CUSTOM_MIRRORS_FILE.lstrip(os.path.sep)), recursive=1)
+
+	mymirrors=[]
+
+	if listonly or ("distlocks" not in features):
+		use_locks = 0
+
+	fetch_to_ro = 0
+	if "skiprocheck" in features:
+		fetch_to_ro = 1
+
+	if not os.access(mysettings["DISTDIR"],os.W_OK) and fetch_to_ro:
+		if use_locks:
+			writemsg(red("!!! For fetching to a read-only filesystem, " + \
+				"locking should be turned off.\n"), noiselevel=-1)
+			writemsg("!!! This can be done by adding -distlocks to " + \
+				"FEATURES in /etc/make.conf\n", noiselevel=-1)
+#			use_locks = 0
+
+	# local mirrors are always added
+	if custommirrors.has_key("local"):
+		mymirrors += custommirrors["local"]
+
+	if ("nomirror" in mysettings["RESTRICT"].split()) or \
+	   ("mirror"   in mysettings["RESTRICT"].split()):
+		# We don't add any mirrors.
+		pass
+	else:
+		if try_mirrors:
+			mymirrors += [x.rstrip("/") for x in mysettings["GENTOO_MIRRORS"].split() if x]
+
+	mydigests = Manifest(
+		mysettings["O"], mysettings["DISTDIR"]).getTypeDigests("DIST")
+
+	fsmirrors = []
+	for x in range(len(mymirrors)-1,-1,-1):
+		if mymirrors[x] and mymirrors[x][0]=='/':
+			fsmirrors += [mymirrors[x]]
+			del mymirrors[x]
+
+	restrict_fetch = "fetch" in mysettings["RESTRICT"].split()
+	custom_local_mirrors = custommirrors.get("local", [])
+	if restrict_fetch:
+		# With fetch restriction, a normal uri may only be fetched from
+		# custom local mirrors (if available).  A mirror:// uri may also
+		# be fetched from specific mirrors (effectively overriding fetch
+		# restriction, but only for specific mirrors).
+		locations = custom_local_mirrors
+	else:
+		locations = mymirrors
+
+	filedict={}
+	primaryuri_indexes={}
+	for myuri in myuris:
+		myfile=os.path.basename(myuri)
+		if not filedict.has_key(myfile):
+			filedict[myfile]=[]
+			for y in range(0,len(locations)):
+				filedict[myfile].append(locations[y]+"/distfiles/"+myfile)
+		if myuri[:9]=="mirror://":
+			eidx = myuri.find("/", 9)
+			if eidx != -1:
+				mirrorname = myuri[9:eidx]
+
+				# Try user-defined mirrors first
+				if custommirrors.has_key(mirrorname):
+					for cmirr in custommirrors[mirrorname]:
+						filedict[myfile].append(cmirr+"/"+myuri[eidx+1:])
+						# remove the mirrors we tried from the list of official mirrors
+						if cmirr.strip() in thirdpartymirrors[mirrorname]:
+							thirdpartymirrors[mirrorname].remove(cmirr)
+				# now try the official mirrors
+				if thirdpartymirrors.has_key(mirrorname):
+					shuffle(thirdpartymirrors[mirrorname])
+
+					for locmirr in thirdpartymirrors[mirrorname]:
+						filedict[myfile].append(locmirr+"/"+myuri[eidx+1:])
+
+				if not filedict[myfile]:
+					writemsg("No known mirror by the name: %s\n" % (mirrorname))
+			else:
+				writemsg("Invalid mirror definition in SRC_URI:\n", noiselevel=-1)
+				writemsg("  %s\n" % (myuri), noiselevel=-1)
+		else:
+			if restrict_fetch:
+				# Only fetch from specific mirrors is allowed.
+				continue
+			if "primaryuri" in mysettings["RESTRICT"].split():
+				# Use the source site first.
+				if primaryuri_indexes.has_key(myfile):
+					primaryuri_indexes[myfile] += 1
+				else:
+					primaryuri_indexes[myfile] = 0
+				filedict[myfile].insert(primaryuri_indexes[myfile], myuri)
+			else:
+				filedict[myfile].append(myuri)
+
+	can_fetch=True
+
+	if listonly:
+		can_fetch = False
+
+	for var_name in ("FETCHCOMMAND", "RESUMECOMMAND"):
+		if not mysettings.get(var_name, None):
+			can_fetch = False
+
+	if can_fetch:
+		dirmode  = 02070
+		filemode =   060
+		modemask =    02
+		distdir_dirs = [""]
+		if "distlocks" in features:
+			distdir_dirs.append(".locks")
+		try:
+			
+			for x in distdir_dirs:
+				mydir = os.path.join(mysettings["DISTDIR"], x)
+				if portage_util.ensure_dirs(mydir, gid=portage_gid, mode=dirmode, mask=modemask):
+					writemsg("Adjusting permissions recursively: '%s'\n" % mydir,
+						noiselevel=-1)
+					def onerror(e):
+						raise # bail out on the first error that occurs during recursion
+					if not apply_recursive_permissions(mydir,
+						gid=portage_gid, dirmode=dirmode, dirmask=modemask,
+						filemode=filemode, filemask=modemask, onerror=onerror):
+						raise portage_exception.OperationNotPermitted(
+							"Failed to apply recursive permissions for the portage group.")
+		except portage_exception.PortageException, e:
+			if not os.path.isdir(mysettings["DISTDIR"]):
+				writemsg("!!! %s\n" % str(e), noiselevel=-1)
+				writemsg("!!! Directory Not Found: DISTDIR='%s'\n" % mysettings["DISTDIR"], noiselevel=-1)
+				writemsg("!!! Fetching will fail!\n", noiselevel=-1)
+
+	if can_fetch and \
+		not fetch_to_ro and \
+		not os.access(mysettings["DISTDIR"], os.W_OK):
+		writemsg("!!! No write access to '%s'\n" % mysettings["DISTDIR"],
+			noiselevel=-1)
+		can_fetch = False
+
+	if can_fetch and use_locks and locks_in_subdir:
+			distlocks_subdir = os.path.join(mysettings["DISTDIR"], locks_in_subdir)
+			if not os.access(distlocks_subdir, os.W_OK):
+				writemsg("!!! No write access to write to %s.  Aborting.\n" % distlocks_subdir,
+					noiselevel=-1)
+				return 0
+			del distlocks_subdir
+	for myfile in filedict.keys():
+		"""
+		fetched  status
+		0        nonexistent
+		1        partially downloaded
+		2        completely downloaded
+		"""
+		myfile_path = os.path.join(mysettings["DISTDIR"], myfile)
+		fetched=0
+		file_lock = None
+		if listonly:
+			writemsg_stdout("\n", noiselevel=-1)
+		else:
+			if use_locks and can_fetch:
+				waiting_msg = None
+				if "parallel-fetch" in features:
+					waiting_msg = ("Downloading '%s'... " + \
+						"see /var/log/emerge-fetch.log for details.") % myfile
+				if locks_in_subdir:
+					file_lock = portage_locks.lockfile(
+						os.path.join(mysettings["DISTDIR"],
+						locks_in_subdir, myfile), wantnewlockfile=1,
+						waiting_msg=waiting_msg)
+				else:
+					file_lock = portage_locks.lockfile(
+						myfile_path, wantnewlockfile=1,
+						waiting_msg=waiting_msg)
+		try:
+			if not listonly:
+				if fsmirrors and not os.path.exists(myfile_path):
+					for mydir in fsmirrors:
+						mirror_file = os.path.join(mydir, myfile)
+						try:
+							shutil.copyfile(mirror_file, myfile_path)
+							writemsg(_("Local mirror has file:" + \
+								" %(file)s\n" % {"file":myfile}))
+							break
+						except (IOError, OSError), e:
+							if e.errno != errno.ENOENT:
+								raise
+							del e
+
+				try:
+					mystat = os.stat(myfile_path)
+				except OSError, e:
+					if e.errno != errno.ENOENT:
+						raise
+					del e
+				else:
+					try:
+						apply_secpass_permissions(
+							myfile_path, gid=portage_gid, mode=0664, mask=02,
+							stat_cached=mystat)
+					except portage_exception.PortageException, e:
+						if not os.access(myfile_path, os.R_OK):
+							writemsg("!!! Failed to adjust permissions:" + \
+								" %s\n" % str(e), noiselevel=-1)
+					if myfile not in mydigests:
+						# We don't have a digest, but the file exists.  We must
+						# assume that it is fully downloaded.
+						continue
+					else:
+						if mystat.st_size < mydigests[myfile]["size"] and \
+							not restrict_fetch:
+							fetched = 1 # Try to resume this download.
+						else:
+							verified_ok, reason = portage_checksum.verify_all(
+								myfile_path, mydigests[myfile])
+							if not verified_ok:
+								writemsg("!!! Previously fetched" + \
+									" file: '%s'\n" % myfile, noiselevel=-1)
+								writemsg("!!! Reason: %s\n" % reason[0],
+									noiselevel=-1)
+								writemsg(("!!! Got:      %s\n" + \
+									"!!! Expected: %s\n") % \
+									(reason[1], reason[2]), noiselevel=-1)
+								if reason[0] == "Insufficient data for checksum verification":
+									return 0
+								if can_fetch and not restrict_fetch:
+									writemsg("Refetching...\n\n",
+										noiselevel=-1)
+									os.unlink(myfile_path)
+							else:
+								eout = output.EOutput()
+								eout.quiet = \
+									mysettings.get("PORTAGE_QUIET", None) == "1"
+								for digest_name in mydigests[myfile]:
+									eout.ebegin(
+										"%s %s ;-)" % (myfile, digest_name))
+									eout.eend(0)
+								continue # fetch any remaining files
+
+			for loc in filedict[myfile]:
+				if listonly:
+					writemsg_stdout(loc+" ", noiselevel=-1)
+					continue
+				# allow different fetchcommands per protocol
+				protocol = loc[0:loc.find("://")]
+				if mysettings.has_key("FETCHCOMMAND_"+protocol.upper()):
+					fetchcommand=mysettings["FETCHCOMMAND_"+protocol.upper()]
+				else:
+					fetchcommand=mysettings["FETCHCOMMAND"]
+				if mysettings.has_key("RESUMECOMMAND_"+protocol.upper()):
+					resumecommand=mysettings["RESUMECOMMAND_"+protocol.upper()]
+				else:
+					resumecommand=mysettings["RESUMECOMMAND"]
+
+				if not can_fetch:
+					if fetched != 2:
+						if fetched == 0:
+							writemsg("!!! File %s isn't fetched but unable to get it.\n" % myfile,
+								noiselevel=-1)
+						else:
+							writemsg("!!! File %s isn't fully fetched, but unable to complete it\n" % myfile,
+								noiselevel=-1)
+						for var_name in ("FETCHCOMMAND", "RESUMECOMMAND"):
+							if not mysettings.get(var_name, None):
+								writemsg(("!!! %s is unset.  It should " + \
+								"have been defined in /etc/make.globals.\n") \
+								 % var_name, noiselevel=-1)
+						return 0
+					else:
+						continue
+
+				if fetched != 2:
+					#we either need to resume or start the download
+					#you can't use "continue" when you're inside a "try" block
+					if fetched==1:
+						#resume mode:
+						writemsg(">>> Resuming download...\n")
+						locfetch=resumecommand
+					else:
+						#normal mode:
+						locfetch=fetchcommand
+					writemsg_stdout(">>> Downloading '%s'\n" % \
+						re.sub(r'//(.+):.+@(.+)/',r'//\1:*password*@\2/', loc))
+					variables = {
+						"DISTDIR": mysettings["DISTDIR"],
+						"URI":     loc,
+						"FILE":    myfile
+					}
+					import shlex, StringIO
+					lexer = shlex.shlex(StringIO.StringIO(locfetch), posix=True)
+					lexer.whitespace_split = True
+					myfetch = [varexpand(x, mydict=variables) for x in lexer]
+
+					spawn_keywords = {}
+					if "userfetch" in mysettings.features and \
+						os.getuid() == 0 and portage_gid and portage_uid:
+						spawn_keywords.update({
+							"uid"    : portage_uid,
+							"gid"    : portage_gid,
+							"groups" : userpriv_groups,
+							"umask"  : 002})
+
+					try:
+
+						if mysettings.selinux_enabled():
+							con = selinux.getcontext()
+							con = con.replace(mysettings["PORTAGE_T"], mysettings["PORTAGE_FETCH_T"])
+							selinux.setexec(con)
+
+						myret = portage_exec.spawn(myfetch,
+							env=mysettings.environ(), **spawn_keywords)
+
+						if mysettings.selinux_enabled():
+							selinux.setexec(None)
+
+					finally:
+						try:
+							apply_secpass_permissions(myfile_path,
+								gid=portage_gid, mode=0664, mask=02)
+						except portage_exception.FileNotFound, e:
+							pass
+						except portage_exception.PortageException, e:
+							if not os.access(myfile_path, os.R_OK):
+								writemsg("!!! Failed to adjust permissions:" + \
+									" %s\n" % str(e), noiselevel=-1)
+
+					if mydigests!=None and mydigests.has_key(myfile):
+						try:
+							mystat = os.stat(myfile_path)
+						except OSError, e:
+							if e.errno != errno.ENOENT:
+								raise
+							del e
+							fetched = 0
+						else:
+							# no exception?  file exists. let digestcheck() report
+							# an appropriately for size or checksum errors
+							if (mystat[stat.ST_SIZE]<mydigests[myfile]["size"]):
+								# Fetch failed... Try the next one... Kill 404 files though.
+								if (mystat[stat.ST_SIZE]<100000) and (len(myfile)>4) and not ((myfile[-5:]==".html") or (myfile[-4:]==".htm")):
+									html404=re.compile("<title>.*(not found|404).*</title>",re.I|re.M)
+									if html404.search(open(mysettings["DISTDIR"]+"/"+myfile).read()):
+										try:
+											os.unlink(mysettings["DISTDIR"]+"/"+myfile)
+											writemsg(">>> Deleting invalid distfile. (Improper 404 redirect from server.)\n")
+											fetched = 0
+											continue
+										except (IOError, OSError):
+											pass
+								fetched = 1
+								continue
+							if not fetchonly:
+								fetched=2
+								break
+							else:
+								# File is the correct size--check the checksums for the fetched
+								# file NOW, for those users who don't have a stable/continuous
+								# net connection. This way we have a chance to try to download
+								# from another mirror...
+								verified_ok,reason = portage_checksum.verify_all(mysettings["DISTDIR"]+"/"+myfile, mydigests[myfile])
+								if not verified_ok:
+									print reason
+									writemsg("!!! Fetched file: "+str(myfile)+" VERIFY FAILED!\n",
+										noiselevel=-1)
+									writemsg("!!! Reason: "+reason[0]+"\n",
+										noiselevel=-1)
+									writemsg("!!! Got:      %s\n!!! Expected: %s\n" % \
+										(reason[1], reason[2]), noiselevel=-1)
+									if reason[0] == "Insufficient data for checksum verification":
+										return 0
+									writemsg("Removing corrupt distfile...\n", noiselevel=-1)
+									os.unlink(mysettings["DISTDIR"]+"/"+myfile)
+									fetched=0
+								else:
+									eout = output.EOutput()
+									eout.quiet = mysettings.get("PORTAGE_QUIET", None) == "1"
+									for x_key in mydigests[myfile].keys():
+										eout.ebegin("%s %s ;-)" % (myfile, x_key))
+										eout.eend(0)
+									fetched=2
+									break
+					else:
+						if not myret:
+							fetched=2
+							break
+						elif mydigests!=None:
+							writemsg("No digest file available and download failed.\n\n",
+								noiselevel=-1)
+		finally:
+			if use_locks and file_lock:
+				portage_locks.unlockfile(file_lock)
+
+		if listonly:
+			writemsg_stdout("\n", noiselevel=-1)
+		if fetched != 2:
+			if restrict_fetch:
+				print "\n!!!", mysettings["CATEGORY"] + "/" + \
+					mysettings["PF"], "has fetch restriction turned on."
+				print "!!! This probably means that this " + \
+					"ebuild's files must be downloaded"
+				print "!!! manually.  See the comments in" + \
+					" the ebuild for more information.\n"
+				spawn(EBUILD_SH_BINARY + " nofetch", mysettings)
+			elif listonly:
+				continue
+			elif not filedict[myfile]:
+				writemsg("Warning: No mirrors available for file" + \
+					" '%s'\n" % (myfile), noiselevel=-1)
+			else:
+				writemsg("!!! Couldn't download '%s'. Aborting.\n" % myfile,
+					noiselevel=-1)
+			return 0
+	return 1
+
+def digestgen(myarchives, mysettings, overwrite=1, manifestonly=0, myportdb=None):
+	"""
+	Generates a digest file if missing.  Assumes all files are available.
+	DEPRECATED: this now only is a compability wrapper for 
+	            portage_manifest.Manifest()
+	NOTE: manifestonly and overwrite are useless with manifest2 and
+	      are therefore ignored."""
+	if myportdb is None:
+		writemsg("Warning: myportdb not specified to digestgen\n")
+		global portdb
+		myportdb = portdb
+	global _doebuild_manifest_exempt_depend
+	try:
+		_doebuild_manifest_exempt_depend += 1
+		distfiles_map = {}
+		fetchlist_dict = FetchlistDict(mysettings["O"], mysettings, myportdb)
+		for cpv in fetchlist_dict:
+			try:
+				for myfile in fetchlist_dict[cpv]:
+					distfiles_map.setdefault(myfile, []).append(cpv)
+			except portage_exception.InvalidDependString, e:
+				writemsg("!!! %s\n" % str(e), noiselevel=-1)
+				writemsg("!!! Invalid SRC_URI for '%s'.\n" % cpv, noiselevel=-1)
+				del e
+				return 0
+		mytree = os.path.dirname(os.path.dirname(mysettings["O"]))
+		manifest1_compat = not os.path.exists(
+			os.path.join(mytree, "manifest1_obsolete"))
+		mf = Manifest(mysettings["O"], mysettings["DISTDIR"],
+			fetchlist_dict=fetchlist_dict, manifest1_compat=manifest1_compat)
+		# Don't require all hashes since that can trigger excessive
+		# fetches when sufficient digests already exist.  To ease transition
+		# while Manifest 1 is being removed, only require hashes that will
+		# exist before and after the transition.
+		required_hash_types = set()
+		required_hash_types.add("size")
+		required_hash_types.add(portage_const.MANIFEST2_REQUIRED_HASH)
+		dist_hashes = mf.fhashdict.get("DIST", {})
+		missing_hashes = set()
+		for myfile in distfiles_map:
+			myhashes = dist_hashes.get(myfile)
+			if not myhashes:
+				missing_hashes.add(myfile)
+				continue
+			if required_hash_types.difference(myhashes):
+				missing_hashes.add(myfile)
+		if missing_hashes:
+			missing_files = []
+			for myfile in missing_hashes:
+				try:
+					os.stat(os.path.join(mysettings["DISTDIR"], myfile))
+				except OSError, e:
+					if e.errno != errno.ENOENT:
+						raise
+					del e
+					missing_files.append(myfile)
+			if missing_files:
+				mytree = os.path.realpath(os.path.dirname(
+					os.path.dirname(mysettings["O"])))
+				fetch_settings = config(clone=mysettings)
+				debug = mysettings.get("PORTAGE_DEBUG") == "1"
+				for myfile in missing_files:
+					success = False
+					for cpv in distfiles_map[myfile]:
+						myebuild = os.path.join(mysettings["O"],
+							catsplit(cpv)[1] + ".ebuild")
+						# for RESTRICT=fetch, mirror, etc...
+						doebuild_environment(myebuild, "fetch",
+							mysettings["ROOT"], fetch_settings,
+							debug, 1, myportdb)
+						alluris, aalist = myportdb.getfetchlist(
+							cpv, mytree=mytree, all=True,
+							mysettings=fetch_settings)
+						myuris = [uri for uri in alluris \
+							if os.path.basename(uri) == myfile]
+						fetch_settings["A"] = myfile # for use by pkg_nofetch()
+						if fetch(myuris, fetch_settings):
+							success = True
+							break
+					if not success:
+						writemsg(("!!! File %s doesn't exist, can't update " + \
+							"Manifest\n") % myfile, noiselevel=-1)
+						return 0
+		writemsg_stdout(">>> Creating Manifest for %s\n" % mysettings["O"])
+		try:
+			mf.create(requiredDistfiles=myarchives,
+				assumeDistHashesSometimes=True,
+				assumeDistHashesAlways=(
+				"assume-digests" in mysettings.features))
+		except portage_exception.FileNotFound, e:
+			writemsg(("!!! File %s doesn't exist, can't update " + \
+				"Manifest\n") % e, noiselevel=-1)
+			return 0
+		mf.write(sign=False)
+		if "assume-digests" not in mysettings.features:
+			distlist = mf.fhashdict.get("DIST", {}).keys()
+			distlist.sort()
+			auto_assumed = []
+			for filename in distlist:
+				if not os.path.exists(
+					os.path.join(mysettings["DISTDIR"], filename)):
+					auto_assumed.append(filename)
+			if auto_assumed:
+				mytree = os.path.realpath(
+					os.path.dirname(os.path.dirname(mysettings["O"])))
+				cp = os.path.sep.join(mysettings["O"].split(os.path.sep)[-2:])
+				pkgs = myportdb.cp_list(cp, mytree=mytree)
+				pkgs.sort()
+				writemsg_stdout("  digest.assumed" + output.colorize("WARN",
+					str(len(auto_assumed)).rjust(18)) + "\n")
+				for pkg_key in pkgs:
+					fetchlist = myportdb.getfetchlist(pkg_key,
+						mysettings=mysettings, all=True, mytree=mytree)[1]
+					pv = pkg_key.split("/")[1]
+					for filename in auto_assumed:
+						if filename in fetchlist:
+							writemsg_stdout(
+								"   digest-%s::%s\n" % (pv, filename))
+		return 1
+	finally:
+		_doebuild_manifest_exempt_depend -= 1
+
+def digestParseFile(myfilename, mysettings=None):
+	"""(filename) -- Parses a given file for entries matching:
+	<checksumkey> <checksum_hex_string> <filename> <filesize>
+	Ignores lines that don't start with a valid checksum identifier
+	and returns a dict with the filenames as keys and {checksumkey:checksum}
+	as the values.
+	DEPRECATED: this function is now only a compability wrapper for
+	            portage_manifest.Manifest()."""
+
+	mysplit = myfilename.split(os.sep)
+	if mysplit[-2] == "files" and mysplit[-1].startswith("digest-"):
+		pkgdir = os.sep + os.sep.join(mysplit[:-2]).strip(os.sep)
+	elif mysplit[-1] == "Manifest":
+		pkgdir = os.sep + os.sep.join(mysplit[:-1]).strip(os.sep)
+
+	if mysettings is None:
+		global settings
+		mysettings = config(clone=settings)
+
+	return Manifest(pkgdir, mysettings["DISTDIR"]).getDigests()
+
+def digestcheck(myfiles, mysettings, strict=0, justmanifest=0):
+	"""Verifies checksums.  Assumes all files have been downloaded.
+	DEPRECATED: this is now only a compability wrapper for 
+	            portage_manifest.Manifest()."""
+	if not strict:
+		return 1
+	pkgdir = mysettings["O"]
+	manifest_path = os.path.join(pkgdir, "Manifest")
+	if not os.path.exists(manifest_path):
+		writemsg("!!! Manifest file not found: '%s'\n" % manifest_path,
+			noiselevel=-1)
+		if strict:
+			return 0
+	mf = Manifest(pkgdir, mysettings["DISTDIR"])
+	eout = output.EOutput()
+	eout.quiet = mysettings.get("PORTAGE_QUIET", None) == "1"
+	try:
+		eout.ebegin("checking ebuild checksums ;-)")
+		mf.checkTypeHashes("EBUILD")
+		eout.eend(0)
+		eout.ebegin("checking auxfile checksums ;-)")
+		mf.checkTypeHashes("AUX")
+		eout.eend(0)
+		eout.ebegin("checking miscfile checksums ;-)")
+		mf.checkTypeHashes("MISC", ignoreMissingFiles=True)
+		eout.eend(0)
+		for f in myfiles:
+			eout.ebegin("checking %s ;-)" % f)
+			mf.checkFileHashes(mf.findFile(f), f)
+			eout.eend(0)
+	except KeyError, e:
+		eout.eend(1)
+		writemsg("\n!!! Missing digest for %s\n" % str(e), noiselevel=-1)
+		return 0
+	except portage_exception.FileNotFound, e:
+		eout.eend(1)
+		writemsg("\n!!! A file listed in the Manifest could not be found: %s\n" % str(e),
+			noiselevel=-1)
+		return 0
+	except portage_exception.DigestException, e:
+		eout.eend(1)
+		writemsg("\n!!! Digest verification failed:\n", noiselevel=-1)
+		writemsg("!!! %s\n" % e.value[0], noiselevel=-1)
+		writemsg("!!! Reason: %s\n" % e.value[1], noiselevel=-1)
+		writemsg("!!! Got: %s\n" % e.value[2], noiselevel=-1)
+		writemsg("!!! Expected: %s\n" % e.value[3], noiselevel=-1)
+		return 0
+	# Make sure that all of the ebuilds are actually listed in the Manifest.
+	for f in os.listdir(pkgdir):
+		if f.endswith(".ebuild") and not mf.hasFile("EBUILD", f):
+			writemsg("!!! A file is not listed in the Manifest: '%s'\n" % \
+				os.path.join(pkgdir, f), noiselevel=-1)
+			return 0
+	""" epatch will just grab all the patches out of a directory, so we have to
+	make sure there aren't any foreign files that it might grab."""
+	filesdir = os.path.join(pkgdir, "files")
+	for parent, dirs, files in os.walk(filesdir):
+		for d in dirs:
+			if d.startswith(".") or d == "CVS":
+				dirs.remove(d)
+		for f in files:
+			if f.startswith("."):
+				continue
+			f = os.path.join(parent, f)[len(filesdir) + 1:]
+			file_type = mf.findFile(f)
+			if file_type != "AUX" and not f.startswith("digest-"):
+				writemsg("!!! A file is not listed in the Manifest: '%s'\n" % \
+					os.path.join(filesdir, f), noiselevel=-1)
+				return 0
+	return 1
+
+# parse actionmap to spawn ebuild with the appropriate args
+def spawnebuild(mydo,actionmap,mysettings,debug,alwaysdep=0,logfile=None):
+	if alwaysdep or "noauto" not in mysettings.features:
+		# process dependency first
+		if "dep" in actionmap[mydo].keys():
+			retval=spawnebuild(actionmap[mydo]["dep"],actionmap,mysettings,debug,alwaysdep=alwaysdep,logfile=logfile)
+			if retval:
+				return retval
+	kwargs = actionmap[mydo]["args"]
+	mysettings["EBUILD_PHASE"] = mydo
+	phase_retval = spawn(actionmap[mydo]["cmd"] % mydo, mysettings, debug=debug, logfile=logfile, **kwargs)
+	mysettings["EBUILD_PHASE"] = ""
+
+	if not kwargs["droppriv"] and secpass >= 2:
+		""" Privileged phases may have left files that need to be made
+		writable to a less privileged user."""
+		apply_recursive_permissions(mysettings["T"],
+			uid=portage_uid, gid=portage_gid, dirmode=070, dirmask=0,
+			filemode=060, filemask=0)
+
+	if phase_retval == os.EX_OK:
+		if mydo == "install":
+			# User and group bits that match the "portage" user or group are
+			# automatically mapped to PORTAGE_INST_UID and PORTAGE_INST_GID if
+			# necessary.  The chown system call may clear S_ISUID and S_ISGID
+			# bits, so those bits are restored if necessary.
+			inst_uid = int(mysettings["PORTAGE_INST_UID"])
+			inst_gid = int(mysettings["PORTAGE_INST_GID"])
+			for parent, dirs, files in os.walk(mysettings["D"]):
+				for fname in chain(dirs, files):
+					fpath = os.path.join(parent, fname)
+					mystat = os.lstat(fpath)
+					if mystat.st_uid != portage_uid and \
+						mystat.st_gid != portage_gid:
+						continue
+					myuid = -1
+					mygid = -1
+					if mystat.st_uid == portage_uid:
+						myuid = inst_uid
+					if mystat.st_gid == portage_gid:
+						mygid = inst_gid
+					apply_secpass_permissions(fpath, uid=myuid, gid=mygid,
+						mode=mystat.st_mode, stat_cached=mystat,
+						follow_links=False)
+			mycommand = " ".join([MISC_SH_BINARY, "install_qa_check", "install_symlink_html_docs"])
+			qa_retval = spawn(mycommand, mysettings, debug=debug, logfile=logfile, **kwargs)
+			if qa_retval:
+				writemsg("!!! install_qa_check failed; exiting.\n",
+					noiselevel=-1)
+			return qa_retval
+	return phase_retval
+
+
+def eapi_is_supported(eapi):
+	return str(eapi).strip() == str(portage_const.EAPI).strip()
+
+def doebuild_environment(myebuild, mydo, myroot, mysettings, debug, use_cache, mydbapi):
+
+	ebuild_path = os.path.abspath(myebuild)
+	pkg_dir     = os.path.dirname(ebuild_path)
+
+	if mysettings.configdict["pkg"].has_key("CATEGORY"):
+		cat = mysettings.configdict["pkg"]["CATEGORY"]
+	else:
+		cat = os.path.basename(normalize_path(os.path.join(pkg_dir, "..")))
+	mypv = os.path.basename(ebuild_path)[:-7]	
+	mycpv = cat+"/"+mypv
+	mysplit=pkgsplit(mypv,silent=0)
+	if mysplit is None:
+		raise portage_exception.IncorrectParameter(
+			"Invalid ebuild path: '%s'" % myebuild)
+
+	if mydo != "depend":
+		"""For performance reasons, setcpv only triggers reset when it
+		detects a package-specific change in config.  For the ebuild
+		environment, a reset call is forced in order to ensure that the
+		latest env.d variables are used."""
+		mysettings.reset(use_cache=use_cache)
+		mysettings.setcpv(mycpv, use_cache=use_cache, mydb=mydbapi)
+
+	mysettings["EBUILD_PHASE"] = mydo
+
+	mysettings["PORTAGE_MASTER_PID"] = str(os.getpid())
+
+	# We are disabling user-specific bashrc files.
+	mysettings["BASH_ENV"] = INVALID_ENV_FILE
+
+	if debug: # Otherwise it overrides emerge's settings.
+		# We have no other way to set debug... debug can't be passed in
+		# due to how it's coded... Don't overwrite this so we can use it.
+		mysettings["PORTAGE_DEBUG"] = "1"
+
+	mysettings["ROOT"]     = myroot
+	mysettings["STARTDIR"] = getcwd()
+
+	mysettings["EBUILD"]   = ebuild_path
+	mysettings["O"]        = pkg_dir
+	mysettings.configdict["pkg"]["CATEGORY"] = cat
+	mysettings["FILESDIR"] = pkg_dir+"/files"
+	mysettings["PF"]       = mypv
+
+	mysettings["ECLASSDIR"]   = mysettings["PORTDIR"]+"/eclass"
+	mysettings["SANDBOX_LOG"] = mycpv.replace("/", "_-_")
+
+	mysettings["PROFILE_PATHS"] = "\n".join(mysettings.profiles)+"\n"+CUSTOM_PROFILE_PATH
+	mysettings["P"]  = mysplit[0]+"-"+mysplit[1]
+	mysettings["PN"] = mysplit[0]
+	mysettings["PV"] = mysplit[1]
+	mysettings["PR"] = mysplit[2]
+
+	if portage_util.noiselimit < 0:
+		mysettings["PORTAGE_QUIET"] = "1"
+
+	if mydo != "depend":
+		eapi, mysettings["INHERITED"], mysettings["SLOT"], mysettings["RESTRICT"]  = \
+			mydbapi.aux_get(mycpv, ["EAPI", "INHERITED", "SLOT", "RESTRICT"])
+		if not eapi_is_supported(eapi):
+			# can't do anything with this.
+			raise portage_exception.UnsupportedAPIException(mycpv, eapi)
+		mysettings["PORTAGE_RESTRICT"] = " ".join(flatten(
+			portage_dep.use_reduce(portage_dep.paren_reduce(
+			mysettings["RESTRICT"]), uselist=mysettings["USE"].split())))
+
+	if mysplit[2] == "r0":
+		mysettings["PVR"]=mysplit[1]
+	else:
+		mysettings["PVR"]=mysplit[1]+"-"+mysplit[2]
+
+	if mysettings.has_key("PATH"):
+		mysplit=mysettings["PATH"].split(":")
+	else:
+		mysplit=[]
+	if PORTAGE_BIN_PATH not in mysplit:
+		mysettings["PATH"]=PORTAGE_BIN_PATH+":"+mysettings["PATH"]
+
+	# Sandbox needs cannonical paths.
+	mysettings["PORTAGE_TMPDIR"] = os.path.realpath(
+		mysettings["PORTAGE_TMPDIR"])
+	mysettings["BUILD_PREFIX"] = mysettings["PORTAGE_TMPDIR"]+"/portage"
+	mysettings["PKG_TMPDIR"]   = mysettings["PORTAGE_TMPDIR"]+"/binpkgs"
+	
+	# Package {pre,post}inst and {pre,post}rm may overlap, so they must have separate
+	# locations in order to prevent interference.
+	if mydo in ("unmerge", "prerm", "postrm", "cleanrm"):
+		mysettings["PORTAGE_BUILDDIR"] = os.path.join(
+			mysettings["PKG_TMPDIR"],
+			mysettings["CATEGORY"], mysettings["PF"])
+	else:
+		mysettings["PORTAGE_BUILDDIR"] = os.path.join(
+			mysettings["BUILD_PREFIX"],
+			mysettings["CATEGORY"], mysettings["PF"])
+
+	mysettings["HOME"] = os.path.join(mysettings["PORTAGE_BUILDDIR"], "homedir")
+	mysettings["WORKDIR"] = os.path.join(mysettings["PORTAGE_BUILDDIR"], "work")
+	mysettings["D"] = os.path.join(mysettings["PORTAGE_BUILDDIR"], "image") + os.sep
+	mysettings["T"] = os.path.join(mysettings["PORTAGE_BUILDDIR"], "temp")
+
+	mysettings["PORTAGE_BASHRC"] = os.path.join(
+		mysettings["PORTAGE_CONFIGROOT"], EBUILD_SH_ENV_FILE.lstrip(os.path.sep))
+
+	#set up KV variable -- DEP SPEEDUP :: Don't waste time. Keep var persistent.
+	if (mydo!="depend") or not mysettings.has_key("KV"):
+		mykv,err1=ExtractKernelVersion(os.path.join(myroot, "usr/src/linux"))
+		if mykv:
+			# Regular source tree
+			mysettings["KV"]=mykv
+		else:
+			mysettings["KV"]=""
+
+	# Allow color.map to control colors associated with einfo, ewarn, etc...
+	mycolors = []
+	for c in ("GOOD", "WARN", "BAD", "HILITE", "BRACKET"):
+		mycolors.append("%s=$'%s'" % (c, output.codes[c]))
+	mysettings["PORTAGE_COLORMAP"] = "\n".join(mycolors)
+
+def prepare_build_dirs(myroot, mysettings, cleanup):
+
+	clean_dirs = [mysettings["HOME"]]
+
+	# We enable cleanup when we want to make sure old cruft (such as the old
+	# environment) doesn't interfere with the current phase.
+	if cleanup:
+		clean_dirs.append(mysettings["T"])
+
+	for clean_dir in clean_dirs:
+		try:
+			shutil.rmtree(clean_dir)
+		except OSError, oe:
+			if errno.ENOENT == oe.errno:
+				pass
+			elif errno.EPERM == oe.errno:
+				writemsg("%s\n" % oe, noiselevel=-1)
+				writemsg("Operation Not Permitted: rmtree('%s')\n" % \
+					clean_dir, noiselevel=-1)
+				return 1
+			else:
+				raise
+
+	def makedirs(dir_path):
+		try:
+			os.makedirs(dir_path)
+		except OSError, oe:
+			if errno.EEXIST == oe.errno:
+				pass
+			elif errno.EPERM == oe.errno:
+				writemsg("%s\n" % oe, noiselevel=-1)
+				writemsg("Operation Not Permitted: makedirs('%s')\n" % \
+					dir_path, noiselevel=-1)
+				return False
+			else:
+				raise
+		return True
+
+	mysettings["PKG_LOGDIR"] = os.path.join(mysettings["T"], "logging")
+
+	mydirs = [os.path.dirname(mysettings["PORTAGE_BUILDDIR"])]
+	mydirs.append(os.path.dirname(mydirs[-1]))
+
+	try:
+		for mydir in mydirs:
+			portage_util.ensure_dirs(mydir)
+			portage_util.apply_secpass_permissions(mydir,
+				gid=portage_gid, uid=portage_uid, mode=070, mask=0)
+		for dir_key in ("PORTAGE_BUILDDIR", "HOME", "PKG_LOGDIR", "T"):
+			"""These directories don't necessarily need to be group writable.
+			However, the setup phase is commonly run as a privileged user prior
+			to the other phases being run by an unprivileged user.  Currently,
+			we use the portage group to ensure that the unprivleged user still
+			has write access to these directories in any case."""
+			portage_util.ensure_dirs(mysettings[dir_key], mode=0775)
+			portage_util.apply_secpass_permissions(mysettings[dir_key],
+				uid=portage_uid, gid=portage_gid)
+	except portage_exception.PermissionDenied, e:
+		writemsg("Permission Denied: %s\n" % str(e), noiselevel=-1)
+		return 1
+	except portage_exception.OperationNotPermitted, e:
+		writemsg("Operation Not Permitted: %s\n" % str(e), noiselevel=-1)
+		return 1
+	except portage_exception.FileNotFound, e:
+		writemsg("File Not Found: '%s'\n" % str(e), noiselevel=-1)
+		return 1
+
+	features_dirs = {
+		"ccache":{
+			"basedir_var":"CCACHE_DIR",
+			"default_dir":os.path.join(mysettings["PORTAGE_TMPDIR"], "ccache"),
+			"always_recurse":False},
+		"confcache":{
+			"basedir_var":"CONFCACHE_DIR",
+			"default_dir":os.path.join(mysettings["PORTAGE_TMPDIR"], "confcache"),
+			"always_recurse":False},
+		"distcc":{
+			"basedir_var":"DISTCC_DIR",
+			"default_dir":os.path.join(mysettings["BUILD_PREFIX"], ".distcc"),
+			"subdirs":("lock", "state"),
+			"always_recurse":True}
+	}
+	dirmode  = 02070
+	filemode =   060
+	modemask =    02
+	for myfeature, kwargs in features_dirs.iteritems():
+		if myfeature in mysettings.features:
+			basedir = mysettings[kwargs["basedir_var"]]
+			if basedir == "":
+				basedir = kwargs["default_dir"]
+				mysettings[kwargs["basedir_var"]] = basedir
+			try:
+				mydirs = [mysettings[kwargs["basedir_var"]]]
+				if "subdirs" in kwargs:
+					for subdir in kwargs["subdirs"]:
+						mydirs.append(os.path.join(basedir, subdir))
+				for mydir in mydirs:
+					modified = portage_util.ensure_dirs(mydir)
+					# Generally, we only want to apply permissions for
+					# initial creation.  Otherwise, we don't know exactly what
+					# permissions the user wants, so should leave them as-is.
+					if modified or kwargs["always_recurse"]:
+						if modified:
+							writemsg("Adjusting permissions recursively: '%s'\n" % mydir,
+								noiselevel=-1)
+						def onerror(e):
+							raise	# The feature is disabled if a single error
+									# occurs during permissions adjustment.
+						if not apply_recursive_permissions(mydir,
+						gid=portage_gid, dirmode=dirmode, dirmask=modemask,
+						filemode=filemode, filemask=modemask, onerror=onerror):
+							raise portage_exception.OperationNotPermitted(
+								"Failed to apply recursive permissions for the portage group.")
+			except portage_exception.PortageException, e:
+				mysettings.features.remove(myfeature)
+				mysettings["FEATURES"] = " ".join(mysettings.features)
+				writemsg("!!! %s\n" % str(e), noiselevel=-1)
+				writemsg("!!! Failed resetting perms on %s='%s'\n" % \
+					(kwargs["basedir_var"], basedir), noiselevel=-1)
+				writemsg("!!! Disabled FEATURES='%s'\n" % myfeature,
+					noiselevel=-1)
+				time.sleep(5)
+
+	workdir_mode = 0700
+	try:
+		mode = mysettings["PORTAGE_WORKDIR_MODE"]
+		if mode.isdigit():
+			parsed_mode = int(mode, 8)
+		elif mode == "":
+			raise KeyError()
+		else:
+			raise ValueError()
+		if parsed_mode & 07777 != parsed_mode:
+			raise ValueError("Invalid file mode: %s" % mode)
+		else:
+			workdir_mode = parsed_mode
+	except KeyError, e:
+		writemsg("!!! PORTAGE_WORKDIR_MODE is unset, using %s.\n" % oct(workdir_mode))
+	except ValueError, e:
+		if len(str(e)) > 0:
+			writemsg("%s\n" % e)
+		writemsg("!!! Unable to parse PORTAGE_WORKDIR_MODE='%s', using %s.\n" % \
+		(mysettings["PORTAGE_WORKDIR_MODE"], oct(workdir_mode)))
+	mysettings["PORTAGE_WORKDIR_MODE"] = oct(workdir_mode)
+	try:
+		apply_secpass_permissions(mysettings["WORKDIR"],
+		uid=portage_uid, gid=portage_gid, mode=workdir_mode)
+	except portage_exception.FileNotFound:
+		pass # ebuild.sh will create it
+
+	if mysettings.get("PORT_LOGDIR", "") == "":
+		while "PORT_LOGDIR" in mysettings:
+			del mysettings["PORT_LOGDIR"]
+	if "PORT_LOGDIR" in mysettings:
+		try:
+			portage_util.ensure_dirs(mysettings["PORT_LOGDIR"],
+				uid=portage_uid, gid=portage_gid, mode=02770)
+		except portage_exception.PortageException, e:
+			writemsg("!!! %s\n" % str(e), noiselevel=-1)
+			writemsg("!!! Permission issues with PORT_LOGDIR='%s'\n" % \
+				mysettings["PORT_LOGDIR"], noiselevel=-1)
+			writemsg("!!! Disabling logging.\n", noiselevel=-1)
+			while "PORT_LOGDIR" in mysettings:
+				del mysettings["PORT_LOGDIR"]
+	if "PORT_LOGDIR" in mysettings:
+		logid_path = os.path.join(mysettings["PORTAGE_BUILDDIR"], ".logid")
+		if not os.path.exists(logid_path):
+			f = open(logid_path, "w")
+			f.close()
+			del f
+		logid_time = time.strftime("%Y%m%d-%H%M%S",
+			time.gmtime(os.stat(logid_path).st_mtime))
+		mysettings["PORTAGE_LOG_FILE"] = os.path.join(
+			mysettings["PORT_LOGDIR"], "%s:%s:%s.log" % \
+			(mysettings["CATEGORY"], mysettings["PF"], logid_time))
+		del logid_path, logid_time
+	else:
+		# When sesandbox is enabled, only log if PORT_LOGDIR is explicitly
+		# enabled since it is possible that local SELinux security policies
+		# do not allow ouput to be piped out of the sesandbox domain.
+		if not (mysettings.selinux_enabled() and \
+			"sesandbox" in mysettings.features):
+			mysettings["PORTAGE_LOG_FILE"] = os.path.join(
+				mysettings["T"], "build.log")
+
+_doebuild_manifest_exempt_depend = 0
+_doebuild_manifest_checked = None
+
+def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0,
+	fetchonly=0, cleanup=0, dbkey=None, use_cache=1, fetchall=0, tree=None,
+	mydbapi=None, vartree=None, prev_mtimes=None):
+	
+	"""
+	Wrapper function that invokes specific ebuild phases through the spawning
+	of ebuild.sh
+	
+	@param myebuild: name of the ebuild to invoke the phase on (CPV)
+	@type myebuild: String
+	@param mydo: Phase to run
+	@type mydo: String
+	@param myroot: $ROOT (usually '/', see man make.conf)
+	@type myroot: String
+	@param mysettings: Portage Configuration
+	@type mysettings: instance of portage.config
+	@param debug: Turns on various debug information (eg, debug for spawn)
+	@type debug: Boolean
+	@param listonly: Used to wrap fetch(); passed such that fetch only lists files required.
+	@type listonly: Boolean
+	@param fetchonly: Used to wrap fetch(); passed such that files are only fetched (no other actions)
+	@type fetchonly: Boolean
+	@param cleanup: Passed to prepare_build_dirs (TODO: what does it do?)
+	@type cleanup: Boolean
+	@param dbkey: A dict (usually keys and values from the depend phase, such as KEYWORDS, USE, etc..)
+	@type dbkey: Dict or String
+	@param use_cache: Enables the cache
+	@type use_cache: Boolean
+	@param fetchall: Used to wrap fetch(), fetches all URI's (even ones invalid due to USE conditionals)
+	@type fetchall: Boolean
+	@param tree: Which tree to use ('vartree','porttree','bintree', etc..), defaults to 'porttree'
+	@type tree: String
+	@param mydbapi: a dbapi instance to pass to various functions; this should be a portdbapi instance.
+	@type mydbapi: portdbapi instance
+	@param vartree: A instance of vartree; used for aux_get calls, defaults to db[myroot]['vartree']
+	@type vartree: vartree instance
+	@param prev_mtimes: A dict of { filename:mtime } keys used by merge() to do config_protection
+	@type prev_mtimes: dictionary
+	@rtype: Boolean
+	@returns:
+	1. 0 for success
+	2. 1 for error
+	
+	Most errors have an accompanying error message.
+	
+	listonly and fetchonly are only really necessary for operations involving 'fetch'
+	prev_mtimes are only necessary for merge operations.
+	Other variables may not be strictly required, many have defaults that are set inside of doebuild.
+	
+	"""
+	
+	if not tree:
+		writemsg("Warning: tree not specified to doebuild\n")
+		tree = "porttree"
+	global db
+	
+	# chunked out deps for each phase, so that ebuild binary can use it 
+	# to collapse targets down.
+	actionmap_deps={
+	"depend": [],
+	"setup":  [],
+	"unpack": ["setup"],
+	"compile":["unpack"],
+	"test":   ["compile"],
+	"install":["test"],
+	"rpm":    ["install"],
+	"package":["install"],
+	}
+	
+	if mydbapi is None:
+		mydbapi = db[myroot][tree].dbapi
+
+	if vartree is None and mydo in ("merge", "qmerge", "unmerge"):
+		vartree = db[myroot]["vartree"]
+
+	features = mysettings.features
+
+	validcommands = ["help","clean","prerm","postrm","cleanrm","preinst","postinst",
+	                "config","setup","depend","fetch","digest",
+	                "unpack","compile","test","install","rpm","qmerge","merge",
+	                "package","unmerge", "manifest"]
+
+	if mydo not in validcommands:
+		validcommands.sort()
+		writemsg("!!! doebuild: '%s' is not one of the following valid commands:" % mydo,
+			noiselevel=-1)
+		for vcount in range(len(validcommands)):
+			if vcount%6 == 0:
+				writemsg("\n!!! ", noiselevel=-1)
+			writemsg(validcommands[vcount].ljust(11), noiselevel=-1)
+		writemsg("\n", noiselevel=-1)
+		return 1
+
+	if not os.path.exists(myebuild):
+		writemsg("!!! doebuild: %s not found for %s\n" % (myebuild, mydo),
+			noiselevel=-1)
+		return 1
+
+	global _doebuild_manifest_exempt_depend
+
+	if "strict" in features and \
+		"digest" not in features and \
+		tree == "porttree" and \
+		mydo not in ("digest", "manifest", "help") and \
+		not _doebuild_manifest_exempt_depend:
+		# Always verify the ebuild checksums before executing it.
+		pkgdir = os.path.dirname(myebuild)
+		manifest_path = os.path.join(pkgdir, "Manifest")
+		global _doebuild_manifest_checked
+		# Avoid checking the same Manifest several times in a row during a
+		# regen with an empty cache.
+		if _doebuild_manifest_checked != manifest_path:
+			if not os.path.exists(manifest_path):
+				writemsg("!!! Manifest file not found: '%s'\n" % manifest_path,
+					noiselevel=-1)
+				return 1
+			mf = Manifest(pkgdir, mysettings["DISTDIR"])
+			try:
+				mf.checkTypeHashes("EBUILD")
+			except portage_exception.FileNotFound, e:
+				writemsg("!!! A file listed in the Manifest " + \
+					"could not be found: %s\n" % str(e), noiselevel=-1)
+				return 1
+			except portage_exception.DigestException, e:
+				writemsg("!!! Digest verification failed:\n", noiselevel=-1)
+				writemsg("!!! %s\n" % e.value[0], noiselevel=-1)
+				writemsg("!!! Reason: %s\n" % e.value[1], noiselevel=-1)
+				writemsg("!!! Got: %s\n" % e.value[2], noiselevel=-1)
+				writemsg("!!! Expected: %s\n" % e.value[3], noiselevel=-1)
+				return 1
+			# Make sure that all of the ebuilds are actually listed in the
+			# Manifest.
+			for f in os.listdir(pkgdir):
+				if f.endswith(".ebuild") and not mf.hasFile("EBUILD", f):
+					writemsg("!!! A file is not listed in the " + \
+					"Manifest: '%s'\n" % os.path.join(pkgdir, f),
+					noiselevel=-1)
+					return 1
+			_doebuild_manifest_checked = manifest_path
+
+	logfile=None
+	builddir_lock = None
+	try:
+		if mydo in ("digest", "manifest", "help"):
+			# Temporarily exempt the depend phase from manifest checks, in case
+			# aux_get calls trigger cache generation.
+			_doebuild_manifest_exempt_depend += 1
+
+		doebuild_environment(myebuild, mydo, myroot, mysettings, debug,
+			use_cache, mydbapi)
+
+		# get possible slot information from the deps file
+		if mydo == "depend":
+			writemsg("!!! DEBUG: dbkey: %s\n" % str(dbkey), 2)
+			if isinstance(dbkey, dict):
+				mysettings["dbkey"] = ""
+				pr, pw = os.pipe()
+				fd_pipes = {0:0, 1:1, 2:2, 9:pw}
+				mypids = spawn(EBUILD_SH_BINARY + " depend", mysettings,
+					fd_pipes=fd_pipes, returnpid=True)
+				os.close(pw) # belongs exclusively to the child process now
+				maxbytes = 1024
+				mybytes = []
+				while True:
+					mybytes.append(os.read(pr, maxbytes))
+					if not mybytes[-1]:
+						break
+				os.close(pr)
+				mybytes = "".join(mybytes)
+				global auxdbkeys
+				for k, v in izip(auxdbkeys, mybytes.splitlines()):
+					dbkey[k] = v
+				retval = os.waitpid(mypids[0], 0)[1]
+				portage_exec.spawned_pids.remove(mypids[0])
+				# If it got a signal, return the signal that was sent, but
+				# shift in order to distinguish it from a return value. (just
+				# like portage_exec.spawn() would do).
+				if retval & 0xff:
+					return (retval & 0xff) << 8
+				# Otherwise, return its exit code.
+				return retval >> 8
+			elif dbkey:
+				mysettings["dbkey"] = dbkey
+			else:
+				mysettings["dbkey"] = \
+					os.path.join(mysettings.depcachedir, "aux_db_key_temp")
+
+			return spawn(EBUILD_SH_BINARY + " depend", mysettings)
+
+		# Validate dependency metadata here to ensure that ebuilds with invalid
+		# data are never installed (even via the ebuild command).
+		invalid_dep_exempt_phases = \
+			set(["clean", "cleanrm", "help", "prerm", "postrm"])
+		mycpv = mysettings["CATEGORY"] + "/" + mysettings["PF"]
+		dep_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
+		misc_keys = ["LICENSE", "PROVIDE", "RESTRICT", "SRC_URI"]
+		all_keys = dep_keys + misc_keys
+		metadata = dict(izip(all_keys, mydbapi.aux_get(mycpv, all_keys)))
+		class FakeTree(object):
+			def __init__(self, mydb):
+				self.dbapi = mydb
+		dep_check_trees = {myroot:{}}
+		dep_check_trees[myroot]["porttree"] = \
+			FakeTree(fakedbapi(settings=mysettings))
+		for dep_type in dep_keys:
+			mycheck = dep_check(metadata[dep_type], None, mysettings,
+				myuse="all", myroot=myroot, trees=dep_check_trees)
+			if not mycheck[0]:
+				writemsg("%s: %s\n%s\n" % (
+					dep_type, metadata[dep_type], mycheck[1]), noiselevel=-1)
+				if mydo not in invalid_dep_exempt_phases:
+					return 1
+			del dep_type, mycheck
+		for k in misc_keys:
+			try:
+				portage_dep.use_reduce(
+					portage_dep.paren_reduce(metadata[k]), matchall=True)
+			except portage_exception.InvalidDependString, e:
+				writemsg("%s: %s\n%s\n" % (
+					k, metadata[k], str(e)), noiselevel=-1)
+				del e
+				if mydo not in invalid_dep_exempt_phases:
+					return 1
+			del k
+		del mycpv, dep_keys, metadata, misc_keys, FakeTree, dep_check_trees
+
+		if "PORTAGE_TMPDIR" not in mysettings or \
+			not os.path.isdir(mysettings["PORTAGE_TMPDIR"]):
+			writemsg("The directory specified in your " + \
+				"PORTAGE_TMPDIR variable, '%s',\n" % \
+				mysettings.get("PORTAGE_TMPDIR", ""), noiselevel=-1)
+			writemsg("does not exist.  Please create this directory or " + \
+				"correct your PORTAGE_TMPDIR setting.\n", noiselevel=-1)
+			return 1
+
+		# Build directory creation isn't required for any of these.
+		if mydo not in ("digest", "fetch", "help", "manifest"):
+			mystatus = prepare_build_dirs(myroot, mysettings, cleanup)
+			if mystatus:
+				return mystatus
+			# PORTAGE_LOG_FILE is set above by the prepare_build_dirs() call.
+			logfile = mysettings.get("PORTAGE_LOG_FILE", None)
+		if mydo == "unmerge":
+			return unmerge(mysettings["CATEGORY"],
+				mysettings["PF"], myroot, mysettings, vartree=vartree)
+
+		# if any of these are being called, handle them -- running them out of
+		# the sandbox -- and stop now.
+		if mydo in ["clean","cleanrm"]:
+			return spawn(EBUILD_SH_BINARY + " clean", mysettings,
+				debug=debug, free=1, logfile=None)
+		elif mydo == "help":
+			return spawn(EBUILD_SH_BINARY + " " + mydo, mysettings,
+				debug=debug, free=1, logfile=logfile)
+		elif mydo == "setup":
+			infodir = os.path.join(
+				mysettings["PORTAGE_BUILDDIR"], "build-info")
+			if os.path.isdir(infodir):
+				"""Load USE flags for setup phase of a binary package.
+				Ideally, the environment.bz2 would be used instead."""
+				mysettings.load_infodir(infodir)
+			retval = spawn(EBUILD_SH_BINARY + " " + mydo, mysettings,
+				debug=debug, free=1, logfile=logfile)
+			if secpass >= 2:
+				""" Privileged phases may have left files that need to be made
+				writable to a less privileged user."""
+				apply_recursive_permissions(mysettings["T"],
+					uid=portage_uid, gid=portage_gid, dirmode=070, dirmask=0,
+					filemode=060, filemask=0)
+			return retval
+		elif mydo == "preinst":
+			mysettings["IMAGE"] = mysettings["D"]
+			phase_retval = spawn(" ".join((EBUILD_SH_BINARY, mydo)),
+				mysettings, debug=debug, free=1, logfile=logfile)
+			if phase_retval == os.EX_OK:
+				# Post phase logic and tasks that have been factored out of
+				# ebuild.sh.
+				myargs = [MISC_SH_BINARY, "preinst_bsdflags", "preinst_mask",
+					"preinst_sfperms", "preinst_selinux_labels",
+					"preinst_suid_scan"]
+				mysettings["EBUILD_PHASE"] = ""
+				phase_retval = spawn(" ".join(myargs),
+					mysettings, debug=debug, free=1, logfile=logfile)
+				if phase_retval != os.EX_OK:
+					writemsg("!!! post preinst failed; exiting.\n",
+						noiselevel=-1)
+			del mysettings["IMAGE"]
+			return phase_retval
+		elif mydo == "postinst":
+			mysettings.load_infodir(mysettings["O"])
+			phase_retval = spawn(" ".join((EBUILD_SH_BINARY, mydo)),
+				mysettings, debug=debug, free=1, logfile=logfile)
+			if phase_retval == os.EX_OK:
+				# Post phase logic and tasks that have been factored out of
+				# ebuild.sh.
+				myargs = [MISC_SH_BINARY, "postinst_bsdflags"]
+				mysettings["EBUILD_PHASE"] = ""
+				phase_retval = spawn(" ".join(myargs),
+					mysettings, debug=debug, free=1, logfile=logfile)
+				if phase_retval != os.EX_OK:
+					writemsg("!!! post postinst failed; exiting.\n",
+						noiselevel=-1)
+			return phase_retval
+		elif mydo in ["prerm","postrm","config"]:
+			mysettings.load_infodir(mysettings["O"])
+			return spawn(EBUILD_SH_BINARY + " " + mydo,
+				mysettings, debug=debug, free=1, logfile=logfile)
+
+		mycpv = "/".join((mysettings["CATEGORY"], mysettings["PF"]))
+
+		# Make sure we get the correct tree in case there are overlays.
+		mytree = os.path.realpath(
+			os.path.dirname(os.path.dirname(mysettings["O"])))
+		try:
+			newuris, alist = mydbapi.getfetchlist(
+				mycpv, mytree=mytree, mysettings=mysettings)
+			alluris, aalist = mydbapi.getfetchlist(
+				mycpv, mytree=mytree, all=True, mysettings=mysettings)
+		except portage_exception.InvalidDependString, e:
+			writemsg("!!! %s\n" % str(e), noiselevel=-1)
+			writemsg("!!! Invalid SRC_URI for '%s'.\n" % mycpv, noiselevel=-1)
+			del e
+			return 1
+		mysettings["A"] = " ".join(alist)
+		mysettings["AA"] = " ".join(aalist)
+		if ("mirror" in features) or fetchall:
+			fetchme = alluris[:]
+			checkme = aalist[:]
+		elif mydo == "digest":
+			fetchme = alluris[:]
+			checkme = aalist[:]
+			# Skip files that we already have digests for.
+			mf = Manifest(mysettings["O"], mysettings["DISTDIR"])
+			mydigests = mf.getTypeDigests("DIST")
+			required_hash_types = set()
+			required_hash_types.add("size")
+			required_hash_types.add(portage_const.MANIFEST2_REQUIRED_HASH)
+			for filename, hashes in mydigests.iteritems():
+				if not required_hash_types.difference(hashes):
+					checkme = [i for i in checkme if i != filename]
+					fetchme = [i for i in fetchme \
+						if os.path.basename(i) != filename]
+				del filename, hashes
+		else:
+			fetchme = newuris[:]
+			checkme = alist[:]
+
+		# Only try and fetch the files if we are going to need them ...
+		# otherwise, if user has FEATURES=noauto and they run `ebuild clean
+		# unpack compile install`, we will try and fetch 4 times :/
+		need_distfiles = (mydo in ("fetch", "unpack") or \
+			mydo not in ("digest", "manifest") and "noauto" not in features)
+		if need_distfiles and not fetch(
+			fetchme, mysettings, listonly=listonly, fetchonly=fetchonly):
+			return 1
+
+		if mydo == "fetch" and listonly:
+			return 0
+
+		try:
+			if mydo == "manifest":
+				return not digestgen(aalist, mysettings, overwrite=1,
+					manifestonly=1, myportdb=mydbapi)
+			elif mydo == "digest":
+				return not digestgen(aalist, mysettings, overwrite=1,
+					myportdb=mydbapi)
+			elif "digest" in mysettings.features:
+				digestgen(aalist, mysettings, overwrite=0, myportdb=mydbapi)
+		except portage_exception.PermissionDenied, e:
+			writemsg("!!! %s\n" % str(e), noiselevel=-1)
+			if mydo in ("digest", "manifest"):
+				return 1
+
+		# See above comment about fetching only when needed
+		if not digestcheck(checkme, mysettings, ("strict" in features),
+			(mydo not in ["digest","fetch","unpack"] and \
+			mysettings.get("PORTAGE_CALLER", None) == "ebuild" and \
+			"noauto" in features)):
+			return 1
+
+		if mydo == "fetch":
+			return 0
+
+		# remove PORTAGE_ACTUAL_DISTDIR once cvs/svn is supported via SRC_URI
+		if (mydo != "setup" and "noauto" not in features) or mydo == "unpack":
+			orig_distdir = mysettings["DISTDIR"]
+			mysettings["PORTAGE_ACTUAL_DISTDIR"] = orig_distdir
+			edpath = mysettings["DISTDIR"] = \
+				os.path.join(mysettings["PORTAGE_BUILDDIR"], "distdir")
+			if os.path.exists(edpath):
+				try:
+					if os.path.isdir(edpath) and not os.path.islink(edpath):
+						shutil.rmtree(edpath)
+					else:
+						os.unlink(edpath)
+				except OSError:
+					print "!!! Failed reseting ebuild distdir path, " + edpath
+					raise
+			os.mkdir(edpath)
+			apply_secpass_permissions(edpath, uid=portage_uid, mode=0755)
+			try:
+				for file in alist:
+					os.symlink(os.path.join(orig_distdir, file),
+						os.path.join(edpath, file))
+			except OSError:
+				print "!!! Failed symlinking in '%s' to ebuild distdir" % file
+				raise
+
+		#initial dep checks complete; time to process main commands
+
+		nosandbox = (("userpriv" in features) and \
+			("usersandbox" not in features) and \
+			("userpriv" not in mysettings["RESTRICT"]) and \
+			("nouserpriv" not in mysettings["RESTRICT"]))
+		if nosandbox and ("userpriv" not in features or \
+			"userpriv" in mysettings["RESTRICT"] or \
+			"nouserpriv" in mysettings["RESTRICT"]):
+			nosandbox = ("sandbox" not in features and \
+				"usersandbox" not in features)
+
+		sesandbox = mysettings.selinux_enabled() and \
+			"sesandbox" in mysettings.features
+		ebuild_sh = EBUILD_SH_BINARY + " %s"
+		misc_sh = MISC_SH_BINARY + " dyn_%s"
+
+		# args are for the to spawn function
+		actionmap = {
+"depend": {"cmd":ebuild_sh, "args":{"droppriv":1, "free":0,         "sesandbox":0}},
+"setup":  {"cmd":ebuild_sh, "args":{"droppriv":0, "free":1,         "sesandbox":0}},
+"unpack": {"cmd":ebuild_sh, "args":{"droppriv":1, "free":0,         "sesandbox":sesandbox}},
+"compile":{"cmd":ebuild_sh, "args":{"droppriv":1, "free":nosandbox, "sesandbox":sesandbox}},
+"test":   {"cmd":ebuild_sh, "args":{"droppriv":1, "free":nosandbox, "sesandbox":sesandbox}},
+"install":{"cmd":ebuild_sh, "args":{"droppriv":0, "free":0,         "sesandbox":sesandbox}},
+"rpm":    {"cmd":misc_sh,   "args":{"droppriv":0, "free":0,         "sesandbox":0}},
+"package":{"cmd":misc_sh,   "args":{"droppriv":0, "free":0,         "sesandbox":0}},
+		}
+
+		# merge the deps in so we have again a 'full' actionmap
+		# be glad when this can die.
+		for x in actionmap.keys():
+			if len(actionmap_deps.get(x, [])):
+				actionmap[x]["dep"] = ' '.join(actionmap_deps[x])
+
+		if mydo in actionmap.keys():
+			if mydo=="package":
+				portage_util.ensure_dirs(
+					os.path.join(mysettings["PKGDIR"], mysettings["CATEGORY"]))
+				portage_util.ensure_dirs(
+					os.path.join(mysettings["PKGDIR"], "All"))
+			retval = spawnebuild(mydo,
+				actionmap, mysettings, debug, logfile=logfile)
+		elif mydo=="qmerge":
+			# check to ensure install was run.  this *only* pops up when users
+			# forget it and are using ebuild
+			if not os.path.exists(
+				os.path.join(mysettings["PORTAGE_BUILDDIR"], ".installed")):
+				writemsg("!!! mydo=qmerge, but install phase hasn't been ran\n",
+					noiselevel=-1)
+				return 1
+			# qmerge is a special phase that implies noclean.
+			if "noclean" not in mysettings.features:
+				mysettings.features.append("noclean")
+			#qmerge is specifically not supposed to do a runtime dep check
+			retval = merge(
+				mysettings["CATEGORY"], mysettings["PF"], mysettings["D"],
+				os.path.join(mysettings["PORTAGE_BUILDDIR"], "build-info"),
+				myroot, mysettings, myebuild=mysettings["EBUILD"], mytree=tree,
+				mydbapi=mydbapi, vartree=vartree, prev_mtimes=prev_mtimes)
+		elif mydo=="merge":
+			retval = spawnebuild("install", actionmap, mysettings, debug,
+				alwaysdep=1, logfile=logfile)
+			if retval == os.EX_OK:
+				retval = merge(mysettings["CATEGORY"], mysettings["PF"],
+					mysettings["D"], os.path.join(mysettings["PORTAGE_BUILDDIR"],
+					"build-info"), myroot, mysettings,
+					myebuild=mysettings["EBUILD"], mytree=tree, mydbapi=mydbapi,
+					vartree=vartree, prev_mtimes=prev_mtimes)
+		else:
+			print "!!! Unknown mydo:",mydo
+			return 1
+
+		if retval != os.EX_OK and tree == "porttree":
+			for i in xrange(len(mydbapi.porttrees)-1):
+				t = mydbapi.porttrees[i+1]
+				if myebuild.startswith(t):
+					# Display the non-cannonical path, in case it's different, to
+					# prevent confusion.
+					overlays = mysettings["PORTDIR_OVERLAY"].split()
+					try:
+						writemsg("!!! This ebuild is from an overlay: '%s'\n" % \
+							overlays[i], noiselevel=-1)
+					except IndexError:
+						pass
+					break
+		return retval
+
+	finally:
+		if builddir_lock:
+			portage_locks.unlockdir(builddir_lock)
+
+		# Make sure that DISTDIR is restored to it's normal value before we return!
+		if "PORTAGE_ACTUAL_DISTDIR" in mysettings:
+			mysettings["DISTDIR"] = mysettings["PORTAGE_ACTUAL_DISTDIR"]
+			del mysettings["PORTAGE_ACTUAL_DISTDIR"]
+
+		if logfile:
+			try:
+				if os.stat(logfile).st_size == 0:
+					os.unlink(logfile)
+			except OSError:
+				pass
+
+		if mydo in ("digest", "manifest", "help"):
+			# If necessary, depend phase has been triggered by aux_get calls
+			# and the exemption is no longer needed.
+			_doebuild_manifest_exempt_depend -= 1
+
+expandcache={}
+
+def movefile(src,dest,newmtime=None,sstat=None,mysettings=None):
+	"""moves a file from src to dest, preserving all permissions and attributes; mtime will
+	be preserved even when moving across filesystems.  Returns true on success and false on
+	failure.  Move is atomic."""
+	#print "movefile("+str(src)+","+str(dest)+","+str(newmtime)+","+str(sstat)+")"
+	global lchown
+	if mysettings is None:
+		global settings
+		mysettings = settings
+	selinux_enabled = mysettings.selinux_enabled()
+	try:
+		if not sstat:
+			sstat=os.lstat(src)
+
+	except SystemExit, e:
+		raise
+	except Exception, e:
+		print "!!! Stating source file failed... movefile()"
+		print "!!!",e
+		return None
+
+	destexists=1
+	try:
+		dstat=os.lstat(dest)
+	except (OSError, IOError):
+		dstat=os.lstat(os.path.dirname(dest))
+		destexists=0
+
+	if bsd_chflags:
+		# Check that we can actually unset schg etc flags...
+		# Clear the flags on source and destination; we'll reinstate them after merging
+		if destexists and dstat.st_flags != 0:
+			if bsd_chflags.lchflags(dest, 0) < 0:
+				writemsg("!!! Couldn't clear flags on file being merged: \n ",
+					noiselevel=-1)
+		# We might have an immutable flag on the parent dir; save and clear.
+		pflags=bsd_chflags.lgetflags(os.path.dirname(dest))
+		if pflags != 0:
+			bsd_chflags.lchflags(os.path.dirname(dest), 0)
+
+		if (destexists and bsd_chflags.lhasproblems(dest) > 0) or \
+			bsd_chflags.lhasproblems(os.path.dirname(dest)) > 0:
+			# This is bad: we can't merge the file with these flags set.
+			writemsg("!!! Can't merge file "+dest+" because of flags set\n",
+				noiselevel=-1)
+			return None
+
+	if destexists:
+		if stat.S_ISLNK(dstat[stat.ST_MODE]):
+			try:
+				os.unlink(dest)
+				destexists=0
+			except SystemExit, e:
+				raise
+			except Exception, e:
+				pass
+
+	if stat.S_ISLNK(sstat[stat.ST_MODE]):
+		try:
+			target=os.readlink(src)
+			if mysettings and mysettings["D"]:
+				if target.find(mysettings["D"])==0:
+					target=target[len(mysettings["D"]):]
+			if destexists and not stat.S_ISDIR(dstat[stat.ST_MODE]):
+				os.unlink(dest)
+			if selinux_enabled:
+				sid = selinux.get_lsid(src)
+				selinux.secure_symlink(target,dest,sid)
+			else:
+				os.symlink(target,dest)
+			lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
+			return os.lstat(dest)[stat.ST_MTIME]
+		except SystemExit, e:
+			raise
+		except Exception, e:
+			print "!!! failed to properly create symlink:"
+			print "!!!",dest,"->",target
+			print "!!!",e
+			return None
+
+	renamefailed=1
+	if sstat[stat.ST_DEV]==dstat[stat.ST_DEV] or selinux_enabled:
+		try:
+			if selinux_enabled:
+				ret=selinux.secure_rename(src,dest)
+			else:
+				ret=os.rename(src,dest)
+			renamefailed=0
+		except SystemExit, e:
+			raise
+		except Exception, e:
+			if e[0]!=errno.EXDEV:
+				# Some random error.
+				print "!!! Failed to move",src,"to",dest
+				print "!!!",e
+				return None
+			# Invalid cross-device-link 'bind' mounted or actually Cross-Device
+	if renamefailed:
+		didcopy=0
+		if stat.S_ISREG(sstat[stat.ST_MODE]):
+			try: # For safety copy then move it over.
+				if selinux_enabled:
+					selinux.secure_copy(src,dest+"#new")
+					selinux.secure_rename(dest+"#new",dest)
+				else:
+					shutil.copyfile(src,dest+"#new")
+					os.rename(dest+"#new",dest)
+				didcopy=1
+			except SystemExit, e:
+				raise
+			except Exception, e:
+				print '!!! copy',src,'->',dest,'failed.'
+				print "!!!",e
+				return None
+		else:
+			#we don't yet handle special, so we need to fall back to /bin/mv
+			if selinux_enabled:
+				a=commands.getstatusoutput(MOVE_BINARY+" -c -f "+"'"+src+"' '"+dest+"'")
+			else:
+				a=commands.getstatusoutput(MOVE_BINARY+" -f "+"'"+src+"' '"+dest+"'")
+				if a[0]!=0:
+					print "!!! Failed to move special file:"
+					print "!!! '"+src+"' to '"+dest+"'"
+					print "!!!",a
+					return None # failure
+		try:
+			if didcopy:
+				if stat.S_ISLNK(sstat[stat.ST_MODE]):
+					lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
+				else:
+					os.chown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
+				os.chmod(dest, stat.S_IMODE(sstat[stat.ST_MODE])) # Sticky is reset on chown
+				os.unlink(src)
+		except SystemExit, e:
+			raise
+		except Exception, e:
+			print "!!! Failed to chown/chmod/unlink in movefile()"
+			print "!!!",dest
+			print "!!!",e
+			return None
+
+	if newmtime:
+		os.utime(dest,(newmtime,newmtime))
+	else:
+		os.utime(dest, (sstat[stat.ST_ATIME], sstat[stat.ST_MTIME]))
+		newmtime=sstat[stat.ST_MTIME]
+
+	if bsd_chflags:
+		# Restore the flags we saved before moving
+		if pflags and bsd_chflags.lchflags(os.path.dirname(dest), pflags) < 0:
+			writemsg("!!! Couldn't restore flags (%s) on '%s'\n" % \
+				(str(pflags), os.path.dirname(dest)), noiselevel=-1)
+			return None
+
+	return newmtime
+
+def merge(mycat, mypkg, pkgloc, infloc, myroot, mysettings, myebuild=None,
+	mytree=None, mydbapi=None, vartree=None, prev_mtimes=None):
+	if not os.access(myroot, os.W_OK):
+		writemsg("Permission denied: access('%s', W_OK)\n" % myroot,
+			noiselevel=-1)
+		return errno.EACCES
+	mylink = dblink(mycat, mypkg, myroot, mysettings, treetype=mytree,
+		vartree=vartree)
+	return mylink.merge(pkgloc, infloc, myroot, myebuild,
+		mydbapi=mydbapi, prev_mtimes=prev_mtimes)
+
+def unmerge(cat, pkg, myroot, mysettings, mytrimworld=1, vartree=None, ldpath_mtimes=None):
+	mylink = dblink(
+		cat, pkg, myroot, mysettings, treetype="vartree", vartree=vartree)
+	try:
+		mylink.lockdb()
+		if mylink.exists():
+			retval = mylink.unmerge(trimworld=mytrimworld, cleanup=1,
+				ldpath_mtimes=ldpath_mtimes)
+			if retval == os.EX_OK:
+				mylink.delete()
+			return retval
+		return os.EX_OK
+	finally:
+		mylink.unlockdb()
+
+def getCPFromCPV(mycpv):
+	"""Calls pkgsplit on a cpv and returns only the cp."""
+	return pkgsplit(mycpv)[0]
+
+def dep_virtual(mysplit, mysettings):
+	"Does virtual dependency conversion"
+	newsplit=[]
+	myvirtuals = mysettings.getvirtuals()
+	for x in mysplit:
+		if type(x)==types.ListType:
+			newsplit.append(dep_virtual(x, mysettings))
+		else:
+			mykey=dep_getkey(x)
+			mychoices = myvirtuals.get(mykey, None)
+			if mychoices:
+				if len(mychoices) == 1:
+					a = x.replace(mykey, mychoices[0])
+				else:
+					if x[0]=="!":
+						# blocker needs "and" not "or(||)".
+						a=[]
+					else:
+						a=['||']
+					for y in mychoices:
+						a.append(x.replace(mykey, y))
+				newsplit.append(a)
+			else:
+				newsplit.append(x)
+	return newsplit
+
+def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
+	trees=None, **kwargs):
+	"""Recursively expand new-style virtuals so as to collapse one or more
+	levels of indirection.  In dep_zapdeps, new-style virtuals will be assigned
+	zero cost regardless of whether or not they are currently installed. Virtual
+	blockers are supported but only when the virtual expands to a single
+	atom because it wouldn't necessarily make sense to block all the components
+	of a compound virtual.  When more than one new-style virtual is matched,
+	the matches are sorted from highest to lowest versions and the atom is
+	expanded to || ( highest match ... lowest match )."""
+	newsplit = []
+	# According to GLEP 37, RDEPEND is the only dependency type that is valid
+	# for new-style virtuals.  Repoman should enforce this.
+	dep_keys = ["RDEPEND", "DEPEND", "PDEPEND"]
+	def compare_pkgs(a, b):
+		return pkgcmp(b[1], a[1])
+	portdb = trees[myroot]["porttree"].dbapi
+	if kwargs["use_binaries"]:
+		portdb = trees[myroot]["bintree"].dbapi
+	myvirtuals = mysettings.getvirtuals()
+	for x in mysplit:
+		if x == "||":
+			newsplit.append(x)
+			continue
+		elif isinstance(x, list):
+			newsplit.append(_expand_new_virtuals(x, edebug, mydbapi,
+				mysettings, myroot=myroot, trees=trees, **kwargs))
+			continue
+		if portage_dep._dep_check_strict and \
+			not isvalidatom(x, allow_blockers=True):
+			raise portage_exception.ParseError(
+				"invalid atom: '%s'" % x)
+		mykey = dep_getkey(x)
+		if not mykey.startswith("virtual/"):
+			newsplit.append(x)
+			continue
+		mychoices = myvirtuals.get(mykey, [])
+		isblocker = x.startswith("!")
+		match_atom = x
+		if isblocker:
+			match_atom = x[1:]
+		pkgs = {}
+		for cpv in portdb.match(match_atom):
+			# only use new-style matches
+			if cpv.startswith("virtual/"):
+				pkgs[cpv] = (cpv, catpkgsplit(cpv)[1:], portdb)
+		if kwargs["use_binaries"] and "vartree" in trees[myroot]:
+			vardb = trees[myroot]["vartree"].dbapi
+			for cpv in vardb.match(match_atom):
+				# only use new-style matches
+				if cpv.startswith("virtual/"):
+					if cpv in pkgs:
+						continue
+					pkgs[cpv] = (cpv, catpkgsplit(cpv)[1:], vardb)
+		if not (pkgs or mychoices):
+			# This one couldn't be expanded as a new-style virtual.  Old-style
+			# virtuals have already been expanded by dep_virtual, so this one
+			# is unavailable and dep_zapdeps will identify it as such.  The
+			# atom is not eliminated here since it may still represent a
+			# dependency that needs to be satisfied.
+			newsplit.append(x)
+			continue
+		if not pkgs and len(mychoices) == 1:
+			newsplit.append(x.replace(mykey, mychoices[0]))
+			continue
+		pkgs = pkgs.values()
+		pkgs.sort(compare_pkgs) # Prefer higher versions.
+		if isblocker:
+			a = []
+		else:
+			a = ['||']
+		for y in pkgs:
+			depstring = " ".join(y[2].aux_get(y[0], dep_keys))
+			if edebug:
+				print "Virtual Parent:   ", y[0]
+				print "Virtual Depstring:", depstring
+			mycheck = dep_check(depstring, mydbapi, mysettings, myroot=myroot,
+				trees=trees, **kwargs)
+			if not mycheck[0]:
+				raise portage_exception.ParseError(
+					"%s: %s '%s'" % (y[0], mycheck[1], depstring))
+			if isblocker:
+				virtual_atoms = [atom for atom in mycheck[1] \
+					if not atom.startswith("!")]
+				if len(virtual_atoms) == 1:
+					# It wouldn't make sense to block all the components of a
+					# compound virtual, so only a single atom block is allowed.
+					a.append("!" + virtual_atoms[0])
+			else:
+				mycheck[1].append("="+y[0]) # pull in the new-style virtual
+				a.append(mycheck[1])
+		# Plain old-style virtuals.  New-style virtuals are preferred.
+		for y in mychoices:
+			a.append(x.replace(mykey, y))
+		if isblocker and not a:
+			# Probably a compound virtual.  Pass the atom through unprocessed.
+			newsplit.append(x)
+			continue
+		newsplit.append(a)
+	return newsplit
+
+def dep_eval(deplist):
+	if not deplist:
+		return 1
+	if deplist[0]=="||":
+		#or list; we just need one "1"
+		for x in deplist[1:]:
+			if type(x)==types.ListType:
+				if dep_eval(x)==1:
+					return 1
+			elif x==1:
+					return 1
+		#XXX: unless there's no available atoms in the list
+		#in which case we need to assume that everything is
+		#okay as some ebuilds are relying on an old bug.
+		if len(deplist) == 1:
+			return 1
+		return 0
+	else:
+		for x in deplist:
+			if type(x)==types.ListType:
+				if dep_eval(x)==0:
+					return 0
+			elif x==0 or x==2:
+				return 0
+		return 1
+
+def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
+	"""Takes an unreduced and reduced deplist and removes satisfied dependencies.
+	Returned deplist contains steps that must be taken to satisfy dependencies."""
+	if trees is None:
+		global db
+		trees = db
+	writemsg("ZapDeps -- %s\n" % (use_binaries), 2)
+	if not reduced or unreduced == ["||"] or dep_eval(reduced):
+		return []
+
+	if unreduced[0] != "||":
+		unresolved = []
+		for dep, satisfied in izip(unreduced, reduced):
+			if isinstance(dep, list):
+				unresolved += dep_zapdeps(dep, satisfied, myroot,
+					use_binaries=use_binaries, trees=trees)
+			elif not satisfied:
+				unresolved.append(dep)
+		return unresolved
+
+	# We're at a ( || atom ... ) type level and need to make a choice
+	deps = unreduced[1:]
+	satisfieds = reduced[1:]
+
+	# Our preference order is for an the first item that:
+	# a) contains all unmasked packages with the same key as installed packages
+	# b) contains all unmasked packages
+	# c) contains masked installed packages
+	# d) is the first item
+
+	preferred = []
+	preferred_any_slot = []
+	possible_upgrades = []
+	other = []
+
+	# Alias the trees we'll be checking availability against
+	vardb = None
+	if "vartree" in trees[myroot]:
+		vardb = trees[myroot]["vartree"].dbapi
+	if use_binaries:
+		mydbapi = trees[myroot]["bintree"].dbapi
+	else:
+		mydbapi = trees[myroot]["porttree"].dbapi
+
+	# Sort the deps into preferred (installed) and other
+	# with values of [[required_atom], availablility]
+	for dep, satisfied in izip(deps, satisfieds):
+		if isinstance(dep, list):
+			atoms = dep_zapdeps(dep, satisfied, myroot,
+				use_binaries=use_binaries, trees=trees)
+		else:
+			atoms = [dep]
+
+		if not vardb:
+			# called by repoman
+			other.append((atoms, None, False))
+			continue
+
+		all_available = True
+		versions = {}
+		for atom in atoms:
+			avail_pkg = best(mydbapi.match(atom))
+			if not avail_pkg and use_binaries:
+				# With --usepkgonly, count installed packages as "available".
+				# Note that --usepkgonly currently has no package.mask support.
+				# See bug #149816.
+				avail_pkg = best(vardb.match(atom))
+			if not avail_pkg:
+				all_available = False
+				break
+			avail_slot = "%s:%s" % (dep_getkey(atom),
+				mydbapi.aux_get(avail_pkg, ["SLOT"])[0])
+			versions[avail_slot] = avail_pkg
+
+		this_choice = (atoms, versions, all_available)
+		if all_available:
+			# The "all installed" criterion is not version or slot specific.
+			# If any version of a package is installed then we assume that it
+			# is preferred over other possible packages choices.
+			all_installed = True
+			for atom in set([dep_getkey(atom) for atom in atoms]):
+				# New-style virtuals have zero cost to install.
+				if not vardb.match(atom) and not atom.startswith("virtual/"):
+					all_installed = False
+					break
+			all_installed_slots = False
+			if all_installed:
+				all_installed_slots = True
+				for slot_atom in versions:
+					# New-style virtuals have zero cost to install.
+					if not vardb.match(slot_atom) and \
+						not slot_atom.startswith("virtual/"):
+						all_installed_slots = False
+						break
+			if all_installed:
+				if all_installed_slots:
+					preferred.append(this_choice)
+				else:
+					preferred_any_slot.append(this_choice)
+			else:
+				possible_upgrades.append(this_choice)
+		else:
+			other.append(this_choice)
+
+	# Compare the "all_installed" choices against the "all_available" choices
+	# for possible missed upgrades.  The main purpose of this code is to find
+	# upgrades of new-style virtuals since _expand_new_virtuals() expands them
+	# into || ( highest version ... lowest version ).  We want to prefer the
+	# highest all_available version of the new-style virtual when there is a
+	# lower all_installed version.
+	preferred.extend(preferred_any_slot)
+	preferred.extend(possible_upgrades)
+	possible_upgrades = preferred[1:]
+	for possible_upgrade in possible_upgrades:
+		atoms, versions, all_available = possible_upgrade
+		myslots = set(versions)
+		for other_choice in preferred:
+			if possible_upgrade is other_choice:
+				# possible_upgrade will not be promoted, so move on
+				break
+			o_atoms, o_versions, o_all_available = other_choice
+			intersecting_slots = myslots.intersection(o_versions)
+			if not intersecting_slots:
+				continue
+			has_upgrade = False
+			has_downgrade = False
+			for myslot in intersecting_slots:
+				myversion = versions[myslot]
+				o_version = o_versions[myslot]
+				if myversion != o_version:
+					if myversion == best([myversion, o_version]):
+						has_upgrade = True
+					else:
+						has_downgrade = True
+						break
+			if has_upgrade and not has_downgrade:
+				preferred.remove(possible_upgrade)
+				o_index = preferred.index(other_choice)
+				preferred.insert(o_index, possible_upgrade)
+				break
+
+	# preferred now contains a) and c) from the order above with
+	# the masked flag differentiating the two. other contains b)
+	# and d) so adding other to preferred will give us a suitable
+	# list to iterate over.
+	preferred.extend(other)
+
+	for allow_masked in (False, True):
+		for atoms, versions, all_available in preferred:
+			if all_available or allow_masked:
+				return atoms
+
+	assert(False) # This point should not be reachable
+
+
+def dep_expand(mydep, mydb=None, use_cache=1, settings=None):
+	if not len(mydep):
+		return mydep
+	if mydep[0]=="*":
+		mydep=mydep[1:]
+	orig_dep = mydep
+	mydep = dep_getcpv(orig_dep)
+	myindex = orig_dep.index(mydep)
+	prefix = orig_dep[:myindex]
+	postfix = orig_dep[myindex+len(mydep):]
+	return prefix + cpv_expand(
+		mydep, mydb=mydb, use_cache=use_cache, settings=settings) + postfix
+
+def dep_check(depstring, mydbapi, mysettings, use="yes", mode=None, myuse=None,
+	use_cache=1, use_binaries=0, myroot="/", trees=None):
+	"""Takes a depend string and parses the condition."""
+	edebug = mysettings.get("PORTAGE_DEBUG", None) == "1"
+	#check_config_instance(mysettings)
+	if trees is None:
+		trees = globals()["db"]
+	if use=="yes":
+		if myuse is None:
+			#default behavior
+			myusesplit = mysettings["USE"].split()
+		else:
+			myusesplit = myuse
+			# We've been given useflags to use.
+			#print "USE FLAGS PASSED IN."
+			#print myuse
+			#if "bindist" in myusesplit:
+			#	print "BINDIST is set!"
+			#else:
+			#	print "BINDIST NOT set."
+	else:
+		#we are being run by autouse(), don't consult USE vars yet.
+		# WE ALSO CANNOT USE SETTINGS
+		myusesplit=[]
+
+	#convert parenthesis to sublists
+	mysplit = portage_dep.paren_reduce(depstring)
+
+	mymasks = set()
+	useforce = set()
+	useforce.add(mysettings["ARCH"])
+	if use == "all":
+		# This masking/forcing is only for repoman.  In other cases, relevant
+		# masking/forcing should have already been applied via
+		# config.regenerate().  Also, binary or installed packages may have
+		# been built with flags that are now masked, and it would be
+		# inconsistent to mask them now.  Additionally, myuse may consist of
+		# flags from a parent package that is being merged to a $ROOT that is
+		# different from the one that mysettings represents.
+		mymasks.update(mysettings.usemask)
+		mymasks.update(mysettings.archlist())
+		mymasks.discard(mysettings["ARCH"])
+		useforce.update(mysettings.useforce)
+		useforce.difference_update(mymasks)
+	try:
+		mysplit = portage_dep.use_reduce(mysplit, uselist=myusesplit,
+			masklist=mymasks, matchall=(use=="all"), excludeall=useforce)
+	except portage_exception.InvalidDependString, e:
+		return [0, str(e)]
+
+	# Do the || conversions
+	mysplit=portage_dep.dep_opconvert(mysplit)
+
+	if mysplit == []:
+		#dependencies were reduced to nothing
+		return [1,[]]
+
+	# Recursively expand new-style virtuals so as to
+	# collapse one or more levels of indirection.
+	try:
+		mysplit = _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings,
+			use=use, mode=mode, myuse=myuse, use_cache=use_cache,
+			use_binaries=use_binaries, myroot=myroot, trees=trees)
+	except portage_exception.ParseError, e:
+		return [0, str(e)]
+
+	mysplit2=mysplit[:]
+	mysplit2=dep_wordreduce(mysplit2,mysettings,mydbapi,mode,use_cache=use_cache)
+	if mysplit2 is None:
+		return [0,"Invalid token"]
+
+	writemsg("\n\n\n", 1)
+	writemsg("mysplit:  %s\n" % (mysplit), 1)
+	writemsg("mysplit2: %s\n" % (mysplit2), 1)
+
+	myzaps = dep_zapdeps(mysplit, mysplit2, myroot,
+		use_binaries=use_binaries, trees=trees)
+	mylist = flatten(myzaps)
+	writemsg("myzaps:   %s\n" % (myzaps), 1)
+	writemsg("mylist:   %s\n" % (mylist), 1)
+	#remove duplicates
+	mydict={}
+	for x in mylist:
+		mydict[x]=1
+	writemsg("mydict:   %s\n" % (mydict), 1)
+	return [1,mydict.keys()]
+
+def dep_wordreduce(mydeplist,mysettings,mydbapi,mode,use_cache=1):
+	"Reduces the deplist to ones and zeros"
+	deplist=mydeplist[:]
+	for mypos in xrange(len(deplist)):
+		if type(deplist[mypos])==types.ListType:
+			#recurse
+			deplist[mypos]=dep_wordreduce(deplist[mypos],mysettings,mydbapi,mode,use_cache=use_cache)
+		elif deplist[mypos]=="||":
+			pass
+		else:
+			mykey = dep_getkey(deplist[mypos])
+			if mysettings and mysettings.pprovideddict.has_key(mykey) and \
+			        match_from_list(deplist[mypos], mysettings.pprovideddict[mykey]):
+				deplist[mypos]=True
+			elif mydbapi is None:
+				# Assume nothing is satisfied.  This forces dep_zapdeps to
+				# return all of deps the deps that have been selected
+				# (excluding those satisfied by package.provided).
+				deplist[mypos] = False
+			else:
+				if mode:
+					mydep=mydbapi.xmatch(mode,deplist[mypos])
+				else:
+					mydep=mydbapi.match(deplist[mypos],use_cache=use_cache)
+				if mydep!=None:
+					tmp=(len(mydep)>=1)
+					if deplist[mypos][0]=="!":
+						tmp=False
+					deplist[mypos]=tmp
+				else:
+					#encountered invalid string
+					return None
+	return deplist
+
+def cpv_getkey(mycpv):
+	myslash=mycpv.split("/")
+	mysplit=pkgsplit(myslash[-1])
+	mylen=len(myslash)
+	if mylen==2:
+		return myslash[0]+"/"+mysplit[0]
+	elif mylen==1:
+		return mysplit[0]
+	else:
+		return mysplit
+
+def key_expand(mykey, mydb=None, use_cache=1, settings=None):
+	mysplit=mykey.split("/")
+	if settings is None:
+		settings = globals()["settings"]
+	virts = settings.getvirtuals("/")
+	virts_p = settings.get_virts_p("/")
+	if len(mysplit)==1:
+		if mydb and type(mydb)==types.InstanceType:
+			for x in settings.categories:
+				if mydb.cp_list(x+"/"+mykey,use_cache=use_cache):
+					return x+"/"+mykey
+			if virts_p.has_key(mykey):
+				return(virts_p[mykey][0])
+		return "null/"+mykey
+	elif mydb:
+		if type(mydb)==types.InstanceType:
+			if (not mydb.cp_list(mykey,use_cache=use_cache)) and virts and virts.has_key(mykey):
+				return virts[mykey][0]
+		return mykey
+
+def cpv_expand(mycpv, mydb=None, use_cache=1, settings=None):
+	"""Given a string (packagename or virtual) expand it into a valid
+	cat/package string. Virtuals use the mydb to determine which provided
+	virtual is a valid choice and defaults to the first element when there
+	are no installed/available candidates."""
+	myslash=mycpv.split("/")
+	mysplit=pkgsplit(myslash[-1])
+	if settings is None:
+		settings = globals()["settings"]
+	virts = settings.getvirtuals("/")
+	virts_p = settings.get_virts_p("/")
+	if len(myslash)>2:
+		# this is illegal case.
+		mysplit=[]
+		mykey=mycpv
+	elif len(myslash)==2:
+		if mysplit:
+			mykey=myslash[0]+"/"+mysplit[0]
+		else:
+			mykey=mycpv
+		if mydb and virts and mykey in virts:
+			writemsg("mydb.__class__: %s\n" % (mydb.__class__), 1)
+			if hasattr(mydb, "cp_list"):
+				if not mydb.cp_list(mykey, use_cache=use_cache):
+					writemsg("virts[%s]: %s\n" % (str(mykey),virts[mykey]), 1)
+					mykey_orig = mykey[:]
+					for vkey in virts[mykey]:
+						if mydb.cp_list(vkey,use_cache=use_cache):
+							mykey = vkey
+							writemsg("virts chosen: %s\n" % (mykey), 1)
+							break
+					if mykey == mykey_orig:
+						mykey=virts[mykey][0]
+						writemsg("virts defaulted: %s\n" % (mykey), 1)
+			#we only perform virtual expansion if we are passed a dbapi
+	else:
+		#specific cpv, no category, ie. "foo-1.0"
+		if mysplit:
+			myp=mysplit[0]
+		else:
+			# "foo" ?
+			myp=mycpv
+		mykey=None
+		matches=[]
+		if mydb:
+			for x in settings.categories:
+				if mydb.cp_list(x+"/"+myp,use_cache=use_cache):
+					matches.append(x+"/"+myp)
+		if len(matches) > 1:
+			virtual_name_collision = False
+			if len(matches) == 2:
+				for x in matches:
+					if not x.startswith("virtual/"):
+						# Assume that the non-virtual is desired.  This helps
+						# avoid the ValueError for invalid deps that come from
+						# installed packages (during reverse blocker detection,
+						# for example).
+						mykey = x
+					else:
+						virtual_name_collision = True
+			if not virtual_name_collision:
+				raise ValueError, matches
+		elif matches:
+			mykey=matches[0]
+
+		if not mykey and type(mydb)!=types.ListType:
+			if virts_p.has_key(myp):
+				mykey=virts_p[myp][0]
+			#again, we only perform virtual expansion if we have a dbapi (not a list)
+		if not mykey:
+			mykey="null/"+myp
+	if mysplit:
+		if mysplit[2]=="r0":
+			return mykey+"-"+mysplit[1]
+		else:
+			return mykey+"-"+mysplit[1]+"-"+mysplit[2]
+	else:
+		return mykey
+
+def getmaskingreason(mycpv, settings=None, portdb=None):
+	from portage_util import grablines
+	if settings is None:
+		settings = globals()["settings"]
+	if portdb is None:
+		portdb = globals()["portdb"]
+	mysplit = catpkgsplit(mycpv)
+	if not mysplit:
+		raise ValueError("invalid CPV: %s" % mycpv)
+	if not portdb.cpv_exists(mycpv):
+		raise KeyError("CPV %s does not exist" % mycpv)
+	mycp=mysplit[0]+"/"+mysplit[1]
+
+	# XXX- This is a temporary duplicate of code from the config constructor.
+	locations = [os.path.join(settings["PORTDIR"], "profiles")]
+	locations.extend(settings.profiles)
+	for ov in settings["PORTDIR_OVERLAY"].split():
+		profdir = os.path.join(normalize_path(ov), "profiles")
+		if os.path.isdir(profdir):
+			locations.append(profdir)
+	locations.append(os.path.join(settings["PORTAGE_CONFIGROOT"],
+		USER_CONFIG_PATH.lstrip(os.path.sep)))
+	locations.reverse()
+	pmasklists = [grablines(os.path.join(x, "package.mask"), recursive=1) for x in locations]
+	pmasklines = []
+	while pmasklists: # stack_lists doesn't preserve order so it can't be used
+		pmasklines.extend(pmasklists.pop(0))
+	del pmasklists
+
+	if settings.pmaskdict.has_key(mycp):
+		for x in settings.pmaskdict[mycp]:
+			if mycpv in portdb.xmatch("match-all", x):
+				comment = ""
+				l = "\n"
+				comment_valid = -1
+				for i in xrange(len(pmasklines)):
+					l = pmasklines[i].strip()
+					if l == "":
+						comment = ""
+						comment_valid = -1
+					elif l[0] == "#":
+						comment += (l+"\n")
+						comment_valid = i + 1
+					elif l == x:
+						if comment_valid != i:
+							comment = ""
+						return comment
+					elif comment_valid != -1:
+						# Apparently this comment applies to muliple masks, so
+						# it remains valid until a blank line is encountered.
+						comment_valid += 1
+	return None
+
+def getmaskingstatus(mycpv, settings=None, portdb=None):
+	if settings is None:
+		settings = globals()["settings"]
+	if portdb is None:
+		portdb = globals()["portdb"]
+	mysplit = catpkgsplit(mycpv)
+	if not mysplit:
+		raise ValueError("invalid CPV: %s" % mycpv)
+	if not portdb.cpv_exists(mycpv):
+		raise KeyError("CPV %s does not exist" % mycpv)
+	mycp=mysplit[0]+"/"+mysplit[1]
+
+	rValue = []
+
+	# profile checking
+	revmaskdict=settings.prevmaskdict
+	if revmaskdict.has_key(mycp):
+		for x in revmaskdict[mycp]:
+			if x[0]=="*":
+				myatom = x[1:]
+			else:
+				myatom = x
+			if not match_to_list(mycpv, [myatom]):
+				rValue.append("profile")
+				break
+
+	# package.mask checking
+	maskdict=settings.pmaskdict
+	unmaskdict=settings.punmaskdict
+	if maskdict.has_key(mycp):
+		for x in maskdict[mycp]:
+			if mycpv in portdb.xmatch("match-all", x):
+				unmask=0
+				if unmaskdict.has_key(mycp):
+					for z in unmaskdict[mycp]:
+						if mycpv in portdb.xmatch("match-all",z):
+							unmask=1
+							break
+				if unmask==0:
+					rValue.append("package.mask")
+
+	# keywords checking
+	try:
+		mygroups, eapi = portdb.aux_get(mycpv, ["KEYWORDS", "EAPI"])
+	except KeyError:
+		# The "depend" phase apparently failed for some reason.  An associated
+		# error message will have already been printed to stderr.
+		return ["corruption"]
+	if not eapi_is_supported(eapi):
+		return ["required EAPI %s, supported EAPI %s" % (eapi, portage_const.EAPI)]
+	mygroups = mygroups.split()
+	pgroups = settings["ACCEPT_KEYWORDS"].split()
+	myarch = settings["ARCH"]
+	if pgroups and myarch not in pgroups:
+		"""For operating systems other than Linux, ARCH is not necessarily a
+		valid keyword."""
+		myarch = pgroups[0].lstrip("~")
+	pkgdict = settings.pkeywordsdict
+
+	cp = dep_getkey(mycpv)
+	if pkgdict.has_key(cp):
+		matches = match_to_list(mycpv, pkgdict[cp].keys())
+		for match in matches:
+			pgroups.extend(pkgdict[cp][match])
+		if matches:
+			inc_pgroups = []
+			for x in pgroups:
+				if x != "-*" and x.startswith("-"):
+					try:
+						inc_pgroups.remove(x[1:])
+					except ValueError:
+						pass
+				if x not in inc_pgroups:
+					inc_pgroups.append(x)
+			pgroups = inc_pgroups
+			del inc_pgroups
+
+	kmask = "missing"
+
+	for keyword in pgroups:
+		if keyword in mygroups:
+			kmask=None
+
+	if kmask:
+		fallback = None
+		for gp in mygroups:
+			if gp=="*":
+				kmask=None
+				break
+			elif gp=="-"+myarch:
+				kmask="-"+myarch
+				break
+			elif gp=="~"+myarch:
+				kmask="~"+myarch
+				break
+
+	if kmask:
+		rValue.append(kmask+" keyword")
+	return rValue
+
+class portagetree:
+	def __init__(self, root="/", virtual=None, clone=None, settings=None):
+
+		if clone:
+			self.root=clone.root
+			self.portroot=clone.portroot
+			self.pkglines=clone.pkglines
+		else:
+			self.root=root
+			if settings is None:
+				settings = globals()["settings"]
+			self.settings = settings
+			self.portroot=settings["PORTDIR"]
+			self.virtual=virtual
+			self.dbapi = portdbapi(
+				settings["PORTDIR"], mysettings=settings)
+
+	def dep_bestmatch(self,mydep):
+		"compatibility method"
+		mymatch=self.dbapi.xmatch("bestmatch-visible",mydep)
+		if mymatch is None:
+			return ""
+		return mymatch
+
+	def dep_match(self,mydep):
+		"compatibility method"
+		mymatch=self.dbapi.xmatch("match-visible",mydep)
+		if mymatch is None:
+			return []
+		return mymatch
+
+	def exists_specific(self,cpv):
+		return self.dbapi.cpv_exists(cpv)
+
+	def getallnodes(self):
+		"""new behavior: these are all *unmasked* nodes.  There may or may not be available
+		masked package for nodes in this nodes list."""
+		return self.dbapi.cp_all()
+
+	def getname(self,pkgname):
+		"returns file location for this particular package (DEPRECATED)"
+		if not pkgname:
+			return ""
+		mysplit=pkgname.split("/")
+		psplit=pkgsplit(mysplit[1])
+		return self.portroot+"/"+mysplit[0]+"/"+psplit[0]+"/"+mysplit[1]+".ebuild"
+
+	def resolve_specific(self,myspec):
+		cps=catpkgsplit(myspec)
+		if not cps:
+			return None
+		mykey = key_expand(cps[0]+"/"+cps[1], mydb=self.dbapi,
+			settings=self.settings)
+		mykey=mykey+"-"+cps[2]
+		if cps[3]!="r0":
+			mykey=mykey+"-"+cps[3]
+		return mykey
+
+	def depcheck(self,mycheck,use="yes",myusesplit=None):
+		return dep_check(mycheck,self.dbapi,use=use,myuse=myusesplit)
+
+	def getslot(self,mycatpkg):
+		"Get a slot for a catpkg; assume it exists."
+		myslot = ""
+		try:
+			myslot=self.dbapi.aux_get(mycatpkg,["SLOT"])[0]
+		except SystemExit, e:
+			raise
+		except Exception, e:
+			pass
+		return myslot
+
+
+class dbapi:
+	def __init__(self):
+		pass
+
+	def close_caches(self):
+		pass
+
+	def cp_list(self,cp,use_cache=1):
+		return
+
+	def cpv_all(self):
+		cpv_list = []
+		for cp in self.cp_all():
+			cpv_list.extend(self.cp_list(cp))
+		return cpv_list
+
+	def aux_get(self,mycpv,mylist):
+		"stub code for returning auxiliary db information, such as SLOT, DEPEND, etc."
+		'input: "sys-apps/foo-1.0",["SLOT","DEPEND","HOMEPAGE"]'
+		'return: ["0",">=sys-libs/bar-1.0","http://www.foo.com"] or [] if mycpv not found'
+		raise NotImplementedError
+
+	def match(self,origdep,use_cache=1):
+		mydep = dep_expand(origdep, mydb=self, settings=self.settings)
+		mykey=dep_getkey(mydep)
+		mylist = match_from_list(mydep,self.cp_list(mykey,use_cache=use_cache))
+		myslot = portage_dep.dep_getslot(mydep)
+		if myslot is not None:
+			mylist = [cpv for cpv in mylist \
+				if self.aux_get(cpv, ["SLOT"])[0] == myslot]
+		return mylist
+
+	def match2(self,mydep,mykey,mylist):
+		writemsg("DEPRECATED: dbapi.match2\n")
+		match_from_list(mydep,mylist)
+
+	def invalidentry(self, mypath):
+		if re.search("portage_lockfile$",mypath):
+			if not os.environ.has_key("PORTAGE_MASTER_PID"):
+				writemsg("Lockfile removed: %s\n" % mypath, 1)
+				portage_locks.unlockfile((mypath,None,None))
+			else:
+				# Nothing we can do about it. We're probably sandboxed.
+				pass
+		elif re.search(".*/-MERGING-(.*)",mypath):
+			if os.path.exists(mypath):
+				writemsg(red("INCOMPLETE MERGE:")+" "+mypath+"\n", noiselevel=-1)
+		else:
+			writemsg("!!! Invalid db entry: %s\n" % mypath, noiselevel=-1)
+
+
+
+class fakedbapi(dbapi):
+	"This is a dbapi to use for the emptytree function.  It's empty, but things can be added to it."
+	def __init__(self, settings=None):
+		self.cpvdict={}
+		self.cpdict={}
+		if settings is None:
+			settings = globals()["settings"]
+		self.settings = settings
+		self._match_cache = {}
+
+	def _clear_cache(self):
+		if self._match_cache:
+			self._match_cache = {}
+
+	def match(self, origdep, use_cache=1):
+		result = self._match_cache.get(origdep, None)
+		if result is not None:
+			return result[:]
+		result = dbapi.match(self, origdep, use_cache=use_cache)
+		self._match_cache[origdep] = result
+		return result[:]
+
+	def cpv_exists(self,mycpv):
+		return self.cpvdict.has_key(mycpv)
+
+	def cp_list(self,mycp,use_cache=1):
+		if not self.cpdict.has_key(mycp):
+			return []
+		else:
+			return self.cpdict[mycp]
+
+	def cp_all(self):
+		returnme=[]
+		for x in self.cpdict.keys():
+			returnme.extend(self.cpdict[x])
+		return returnme
+
+	def cpv_all(self):
+		return self.cpvdict.keys()
+
+	def cpv_inject(self, mycpv, metadata=None):
+		"""Adds a cpv from the list of available packages."""
+		self._clear_cache()
+		mycp=cpv_getkey(mycpv)
+		self.cpvdict[mycpv] = metadata
+		myslot = None
+		if metadata:
+			myslot = metadata.get("SLOT", None)
+		if myslot and mycp in self.cpdict:
+			# If necessary, remove another package in the same SLOT.
+			for cpv in self.cpdict[mycp]:
+				if mycpv != cpv:
+					other_metadata = self.cpvdict[cpv]
+					if other_metadata:
+						if myslot == other_metadata.get("SLOT", None):
+							self.cpv_remove(cpv)
+							break
+		if mycp not in self.cpdict:
+			self.cpdict[mycp] = []
+		if not mycpv in self.cpdict[mycp]:
+			self.cpdict[mycp].append(mycpv)
+
+	def cpv_remove(self,mycpv):
+		"""Removes a cpv from the list of available packages."""
+		self._clear_cache()
+		mycp=cpv_getkey(mycpv)
+		if self.cpvdict.has_key(mycpv):
+			del	self.cpvdict[mycpv]
+		if not self.cpdict.has_key(mycp):
+			return
+		while mycpv in self.cpdict[mycp]:
+			del self.cpdict[mycp][self.cpdict[mycp].index(mycpv)]
+		if not len(self.cpdict[mycp]):
+			del self.cpdict[mycp]
+
+	def aux_get(self, mycpv, wants):
+		if not self.cpv_exists(mycpv):
+			raise KeyError(mycpv)
+		metadata = self.cpvdict[mycpv]
+		if not metadata:
+			return ["" for x in wants]
+		return [metadata.get(x, "") for x in wants]
+
+	def aux_update(self, cpv, values):
+		self._clear_cache()
+		self.cpvdict[cpv].update(values)
+
+class bindbapi(fakedbapi):
+	def __init__(self, mybintree=None, settings=None):
+		self.bintree = mybintree
+		self.cpvdict={}
+		self.cpdict={}
+		if settings is None:
+			settings = globals()["settings"]
+		self.settings = settings
+		self._match_cache = {}
+		# Selectively cache metadata in order to optimize dep matching.
+		self._aux_cache_keys = set(["SLOT"])
+		self._aux_cache = {}
+
+	def match(self, *pargs, **kwargs):
+		if self.bintree and not self.bintree.populated:
+			self.bintree.populate()
+		return fakedbapi.match(self, *pargs, **kwargs)
+
+	def aux_get(self,mycpv,wants):
+		if self.bintree and not self.bintree.populated:
+			self.bintree.populate()
+		cache_me = False
+		if not set(wants).difference(self._aux_cache_keys):
+			aux_cache = self._aux_cache.get(mycpv)
+			if aux_cache is not None:
+				return [aux_cache[x] for x in wants]
+			cache_me = True
+		mysplit = mycpv.split("/")
+		mylist  = []
+		tbz2name = mysplit[1]+".tbz2"
+		if self.bintree and not self.bintree.isremote(mycpv):
+			tbz2 = xpak.tbz2(self.bintree.getname(mycpv))
+			getitem = tbz2.getfile
+		else:
+			getitem = self.bintree.remotepkgs[tbz2name].get
+		mydata = {}
+		mykeys = wants
+		if cache_me:
+			mykeys = self._aux_cache_keys.union(wants)
+		for x in mykeys:
+			myval = getitem(x)
+			# myval is None if the key doesn't exist
+			# or the tbz2 is corrupt.
+			if myval:
+				mydata[x] = " ".join(myval.split())
+		if "EAPI" in mykeys:
+			if not mydata.setdefault("EAPI", "0"):
+				mydata["EAPI"] = "0"
+		if cache_me:
+			aux_cache = {}
+			for x in self._aux_cache_keys:
+				aux_cache[x] = mydata.get(x, "")
+			self._aux_cache[mycpv] = aux_cache
+		return [mydata.get(x, "") for x in wants]
+
+	def aux_update(self, cpv, values):
+		if not self.bintree.populated:
+			self.bintree.populate()
+		tbz2path = self.bintree.getname(cpv)
+		if not os.path.exists(tbz2path):
+			raise KeyError(cpv)
+		mytbz2 = xpak.tbz2(tbz2path)
+		mydata = mytbz2.get_data()
+		mydata.update(values)
+		mytbz2.recompose_mem(xpak.xpak_mem(mydata))
+
+	def cp_list(self, *pargs, **kwargs):
+		if not self.bintree.populated:
+			self.bintree.populate()
+		return fakedbapi.cp_list(self, *pargs, **kwargs)
+
+	def cpv_all(self):
+		if not self.bintree.populated:
+			self.bintree.populate()
+		return fakedbapi.cpv_all(self)
+
+class vardbapi(dbapi):
+	def __init__(self, root, categories=None, settings=None, vartree=None):
+		self.root       = root[:]
+		#cache for category directory mtimes
+		self.mtdircache = {}
+		#cache for dependency checks
+		self.matchcache = {}
+		#cache for cp_list results
+		self.cpcache    = {}
+		self.blockers   = None
+		if settings is None:
+			settings = globals()["settings"]
+		self.settings = settings
+		if categories is None:
+			categories = settings.categories
+		self.categories = categories[:]
+		if vartree is None:
+			vartree = globals()["db"][root]["vartree"]
+		self.vartree = vartree
+		self._aux_cache_keys = set(["SLOT", "COUNTER", "PROVIDE", "USE",
+			"IUSE", "DEPEND", "RDEPEND", "PDEPEND"])
+		self._aux_cache = None
+		self._aux_cache_version = "1"
+		self._aux_cache_filename = os.path.join(self.root,
+			CACHE_PATH.lstrip(os.path.sep), "vdb_metadata.pickle")
+
+	def cpv_exists(self,mykey):
+		"Tells us whether an actual ebuild exists on disk (no masking)"
+		return os.path.exists(self.root+VDB_PATH+"/"+mykey)
+
+	def cpv_counter(self,mycpv):
+		"This method will grab the COUNTER. Returns a counter value."
+		try:
+			return long(self.aux_get(mycpv, ["COUNTER"])[0])
+		except (KeyError, ValueError):
+			pass
+		cdir=self.root+VDB_PATH+"/"+mycpv
+		cpath=self.root+VDB_PATH+"/"+mycpv+"/COUNTER"
+
+		# We write our new counter value to a new file that gets moved into
+		# place to avoid filesystem corruption on XFS (unexpected reboot.)
+		corrupted=0
+		if os.path.exists(cpath):
+			cfile=open(cpath, "r")
+			try:
+				counter=long(cfile.readline())
+			except ValueError:
+				print "portage: COUNTER for",mycpv,"was corrupted; resetting to value of 0"
+				counter=long(0)
+				corrupted=1
+			cfile.close()
+		elif os.path.exists(cdir):
+			mys = pkgsplit(mycpv)
+			myl = self.match(mys[0],use_cache=0)
+			print mys,myl
+			if len(myl) == 1:
+				try:
+					# Only one package... Counter doesn't matter.
+					write_atomic(cpath, "1")
+					counter = 1
+				except SystemExit, e:
+					raise
+				except Exception, e:
+					writemsg("!!! COUNTER file is missing for "+str(mycpv)+" in /var/db.\n",
+						noiselevel=-1)
+					writemsg("!!! Please run %s/fix-db.py or\n" % PORTAGE_BIN_PATH,
+						noiselevel=-1)
+					writemsg("!!! unmerge this exact version.\n", noiselevel=-1)
+					writemsg("!!! %s\n" % e, noiselevel=-1)
+					sys.exit(1)
+			else:
+				writemsg("!!! COUNTER file is missing for "+str(mycpv)+" in /var/db.\n",
+					noiselevel=-1)
+				writemsg("!!! Please run %s/fix-db.py or\n" % PORTAGE_BIN_PATH,
+					noiselevel=-1)
+				writemsg("!!! remerge the package.\n", noiselevel=-1)
+				sys.exit(1)
+		else:
+			counter=long(0)
+		if corrupted:
+			# update new global counter file
+			write_atomic(cpath, str(counter))
+		return counter
+
+	def cpv_inject(self,mycpv):
+		"injects a real package into our on-disk database; assumes mycpv is valid and doesn't already exist"
+		os.makedirs(self.root+VDB_PATH+"/"+mycpv)
+		counter = self.counter_tick(self.root, mycpv=mycpv)
+		# write local package counter so that emerge clean does the right thing
+		write_atomic(os.path.join(self.root, VDB_PATH, mycpv, "COUNTER"), str(counter))
+
+	def isInjected(self,mycpv):
+		if self.cpv_exists(mycpv):
+			if os.path.exists(self.root+VDB_PATH+"/"+mycpv+"/INJECTED"):
+				return True
+			if not os.path.exists(self.root+VDB_PATH+"/"+mycpv+"/CONTENTS"):
+				return True
+		return False
+
+	def move_ent(self,mylist):
+		origcp=mylist[1]
+		newcp=mylist[2]
+
+		# sanity check
+		for cp in [origcp,newcp]:
+			if not (isvalidatom(cp) and isjustname(cp)):
+				raise portage_exception.InvalidPackageName(cp)
+		origmatches=self.match(origcp,use_cache=0)
+		if not origmatches:
+			return
+		for mycpv in origmatches:
+			mycpsplit=catpkgsplit(mycpv)
+			mynewcpv=newcp+"-"+mycpsplit[2]
+			mynewcat=newcp.split("/")[0]
+			if mycpsplit[3]!="r0":
+				mynewcpv += "-"+mycpsplit[3]
+			mycpsplit_new = catpkgsplit(mynewcpv)
+			origpath=self.root+VDB_PATH+"/"+mycpv
+			if not os.path.exists(origpath):
+				continue
+			writemsg_stdout("@")
+			if not os.path.exists(self.root+VDB_PATH+"/"+mynewcat):
+				#create the directory
+				os.makedirs(self.root+VDB_PATH+"/"+mynewcat)
+			newpath=self.root+VDB_PATH+"/"+mynewcpv
+			if os.path.exists(newpath):
+				#dest already exists; keep this puppy where it is.
+				continue
+			os.rename(origpath, newpath)
+
+			# We need to rename the ebuild now.
+			old_pf = catsplit(mycpv)[1]
+			new_pf = catsplit(mynewcpv)[1]
+			if new_pf != old_pf:
+				try:
+					os.rename(os.path.join(newpath, old_pf + ".ebuild"),
+						os.path.join(newpath, new_pf + ".ebuild"))
+				except OSError, e:
+					if e.errno != errno.ENOENT:
+						raise
+					del e
+				write_atomic(os.path.join(newpath, "PF"), new_pf+"\n")
+
+			write_atomic(os.path.join(newpath, "CATEGORY"), mynewcat+"\n")
+			fixdbentries([mylist], newpath)
+
+	def update_ents(self, update_iter):
+		"""Run fixdbentries on all installed packages (time consuming).  Like
+		fixpackages, this should be run from a helper script and display
+		a progress indicator."""
+		dbdir = os.path.join(self.root, VDB_PATH)
+		for catdir in listdir(dbdir):
+			catdir = dbdir+"/"+catdir
+			if os.path.isdir(catdir):
+				for pkgdir in listdir(catdir):
+					pkgdir = catdir+"/"+pkgdir
+					if os.path.isdir(pkgdir):
+						fixdbentries(update_iter, pkgdir)
+
+	def move_slot_ent(self,mylist):
+		pkg=mylist[1]
+		origslot=mylist[2]
+		newslot=mylist[3]
+
+		if not isvalidatom(pkg):
+			raise portage_exception.InvalidAtom(pkg)
+
+		origmatches=self.match(pkg,use_cache=0)
+		
+		if not origmatches:
+			return
+		for mycpv in origmatches:
+			origpath=self.root+VDB_PATH+"/"+mycpv
+			if not os.path.exists(origpath):
+				continue
+
+			slot=grabfile(origpath+"/SLOT");
+			if (not slot):
+				continue
+
+			if (slot[0]!=origslot):
+				continue
+
+			writemsg_stdout("s")
+			write_atomic(os.path.join(origpath, "SLOT"), newslot+"\n")
+
+	def cp_list(self,mycp,use_cache=1):
+		mysplit=mycp.split("/")
+		if mysplit[0] == '*':
+			mysplit[0] = mysplit[0][1:]
+		try:
+			mystat=os.stat(self.root+VDB_PATH+"/"+mysplit[0])[stat.ST_MTIME]
+		except OSError:
+			mystat=0
+		if use_cache and self.cpcache.has_key(mycp):
+			cpc=self.cpcache[mycp]
+			if cpc[0]==mystat:
+				return cpc[1]
+		list=listdir(self.root+VDB_PATH+"/"+mysplit[0],EmptyOnError=1)
+
+		if (list is None):
+			return []
+		returnme=[]
+		for x in list:
+			if x.startswith("."):
+				continue
+			if x[0] == '-':
+				#writemsg(red("INCOMPLETE MERGE:")+str(x[len("-MERGING-"):])+"\n")
+				continue
+			ps=pkgsplit(x)
+			if not ps:
+				self.invalidentry(self.root+VDB_PATH+"/"+mysplit[0]+"/"+x)
+				continue
+			if len(mysplit) > 1:
+				if ps[0]==mysplit[1]:
+					returnme.append(mysplit[0]+"/"+x)
+		if use_cache:
+			self.cpcache[mycp]=[mystat,returnme]
+		elif self.cpcache.has_key(mycp):
+			del self.cpcache[mycp]
+		return returnme
+
+	def cpv_all(self,use_cache=1):
+		returnme=[]
+		basepath = self.root+VDB_PATH+"/"
+
+		for x in self.categories:
+			for y in listdir(basepath+x,EmptyOnError=1):
+				if y.startswith("."):
+					continue
+				subpath = x+"/"+y
+				# -MERGING- should never be a cpv, nor should files.
+				if os.path.isdir(basepath+subpath) and (pkgsplit(y) is not None):
+					returnme += [subpath]
+		return returnme
+
+	def cp_all(self,use_cache=1):
+		mylist = self.cpv_all(use_cache=use_cache)
+		d={}
+		for y in mylist:
+			if y[0] == '*':
+				y = y[1:]
+			mysplit=catpkgsplit(y)
+			if not mysplit:
+				self.invalidentry(self.root+VDB_PATH+"/"+y)
+				continue
+			d[mysplit[0]+"/"+mysplit[1]] = None
+		return d.keys()
+
+	def checkblockers(self,origdep):
+		pass
+
+	def match(self,origdep,use_cache=1):
+		"caching match function"
+		mydep = dep_expand(
+			origdep, mydb=self, use_cache=use_cache, settings=self.settings)
+		mykey=dep_getkey(mydep)
+		mycat=mykey.split("/")[0]
+		if not use_cache:
+			if self.matchcache.has_key(mycat):
+				del self.mtdircache[mycat]
+				del self.matchcache[mycat]
+			mymatch = match_from_list(mydep,
+				self.cp_list(mykey, use_cache=use_cache))
+			myslot = portage_dep.dep_getslot(mydep)
+			if myslot is not None:
+				mymatch = [cpv for cpv in mymatch \
+					if self.aux_get(cpv, ["SLOT"])[0] == myslot]
+			return mymatch
+		try:
+			curmtime=os.stat(self.root+VDB_PATH+"/"+mycat)[stat.ST_MTIME]
+		except (IOError, OSError):
+			curmtime=0
+
+		if not self.matchcache.has_key(mycat) or not self.mtdircache[mycat]==curmtime:
+			# clear cache entry
+			self.mtdircache[mycat]=curmtime
+			self.matchcache[mycat]={}
+		if not self.matchcache[mycat].has_key(mydep):
+			mymatch=match_from_list(mydep,self.cp_list(mykey,use_cache=use_cache))
+			myslot = portage_dep.dep_getslot(mydep)
+			if myslot is not None:
+				mymatch = [cpv for cpv in mymatch \
+					if self.aux_get(cpv, ["SLOT"])[0] == myslot]
+			self.matchcache[mycat][mydep]=mymatch
+		return self.matchcache[mycat][mydep][:]
+
+	def findname(self, mycpv):
+		return self.root+VDB_PATH+"/"+str(mycpv)+"/"+mycpv.split("/")[1]+".ebuild"
+
+	def flush_cache(self):
+		"""If the current user has permission and the internal aux_get cache has
+		been updated, save it to disk and mark it unmodified.  This is called
+		by emerge after it has loaded the full vdb for use in dependency
+		calculations.  Currently, the cache is only written if the user has
+		superuser privileges (since that's required to obtain a lock), but all
+		users have read access and benefit from faster metadata lookups (as
+		long as at least part of the cache is still valid)."""
+		if self._aux_cache is not None and \
+			self._aux_cache["modified"] and \
+			secpass >= 2:
+			valid_nodes = set(self.cpv_all())
+			for cpv in self._aux_cache["packages"].keys():
+				if cpv not in valid_nodes:
+					del self._aux_cache["packages"][cpv]
+			del self._aux_cache["modified"]
+			try:
+				f = atomic_ofstream(self._aux_cache_filename)
+				cPickle.dump(self._aux_cache, f, -1)
+				f.close()
+				portage_util.apply_secpass_permissions(
+					self._aux_cache_filename, gid=portage_gid, mode=0644)
+			except (IOError, OSError), e:
+				pass
+			self._aux_cache["modified"] = False
+
+	def aux_get(self, mycpv, wants):
+		"""This automatically caches selected keys that are frequently needed
+		by emerge for dependency calculations.  The cached metadata is
+		considered valid if the mtime of the package directory has not changed
+		since the data was cached.  The cache is stored in a pickled dict
+		object with the following format:
+
+		{version:"1", "packages":{cpv1:(mtime,{k1,v1, k2,v2, ...}), cpv2...}}
+
+		If an error occurs while loading the cache pickle or the version is
+		unrecognized, the cache will simple be recreated from scratch (it is
+		completely disposable).
+		"""
+		if not self._aux_cache_keys.intersection(wants):
+			return self._aux_get(mycpv, wants)
+		if self._aux_cache is None:
+			try:
+				f = open(self._aux_cache_filename)
+				mypickle = cPickle.Unpickler(f)
+				mypickle.find_global = None
+				self._aux_cache = mypickle.load()
+				f.close()
+				del f
+			except (IOError, OSError, EOFError, cPickle.UnpicklingError):
+				pass
+			if not self._aux_cache or \
+				not isinstance(self._aux_cache, dict) or \
+				self._aux_cache.get("version") != self._aux_cache_version or \
+				not self._aux_cache.get("packages"):
+				self._aux_cache = {"version":self._aux_cache_version}
+				self._aux_cache["packages"] = {}
+			self._aux_cache["modified"] = False
+		mydir = os.path.join(self.root, VDB_PATH, mycpv)
+		mydir_stat = None
+		try:
+			mydir_stat = os.stat(mydir)
+		except OSError, e:
+			if e.errno != errno.ENOENT:
+				raise
+			raise KeyError(mycpv)
+		mydir_mtime = long(mydir_stat.st_mtime)
+		pkg_data = self._aux_cache["packages"].get(mycpv)
+		mydata = {}
+		cache_valid = False
+		if pkg_data:
+			cache_mtime, metadata = pkg_data
+			cache_valid = cache_mtime == mydir_mtime
+		if cache_valid:
+			cache_incomplete = self._aux_cache_keys.difference(metadata)
+			if cache_incomplete:
+				# Allow self._aux_cache_keys to change without a cache version
+				# bump and efficiently recycle partial cache whenever possible.
+				cache_valid = False
+				pull_me = cache_incomplete.union(wants)
+			else:
+				pull_me = set(wants).difference(self._aux_cache_keys)
+			mydata.update(metadata)
+		else:
+			pull_me = self._aux_cache_keys.union(wants)
+		if pull_me:
+			# pull any needed data and cache it
+			aux_keys = list(pull_me)
+			for k, v in izip(aux_keys, self._aux_get(mycpv, aux_keys)):
+				mydata[k] = v
+			if not cache_valid:
+				cache_data = {}
+				for aux_key in self._aux_cache_keys:
+					cache_data[aux_key] = mydata[aux_key]
+				self._aux_cache["packages"][mycpv] = (mydir_mtime, cache_data)
+				self._aux_cache["modified"] = True
+		return [mydata[x] for x in wants]
+
+	def _aux_get(self, mycpv, wants):
+		mydir = os.path.join(self.root, VDB_PATH, mycpv)
+		try:
+			if not stat.S_ISDIR(os.stat(mydir).st_mode):
+				raise KeyError(mycpv)
+		except OSError, e:
+			if e.errno == errno.ENOENT:
+				raise KeyError(mycpv)
+			del e
+			raise
+		results = []
+		for x in wants:
+			try:
+				myf = open(os.path.join(mydir, x), "r")
+				try:
+					myd = myf.read()
+				finally:
+					myf.close()
+				myd = " ".join(myd.split())
+			except IOError:
+				myd = ""
+			if x == "EAPI" and not myd:
+				results.append("0")
+			else:
+				results.append(myd)
+		return results
+
+	def aux_update(self, cpv, values):
+		cat, pkg = cpv.split("/")
+		mylink = dblink(cat, pkg, self.root, self.settings,
+		treetype="vartree", vartree=self.vartree)
+		if not mylink.exists():
+			raise KeyError(cpv)
+		for k, v in values.iteritems():
+			mylink.setfile(k, v)
+
+	def counter_tick(self,myroot,mycpv=None):
+		return self.counter_tick_core(myroot,incrementing=1,mycpv=mycpv)
+
+	def get_counter_tick_core(self,myroot,mycpv=None):
+		return self.counter_tick_core(myroot,incrementing=0,mycpv=mycpv)+1
+
+	def counter_tick_core(self,myroot,incrementing=1,mycpv=None):
+		"This method will grab the next COUNTER value and record it back to the global file.  Returns new counter value."
+		cpath=myroot+"var/cache/edb/counter"
+		changed=0
+		min_counter = 0
+		if mycpv:
+			mysplit = pkgsplit(mycpv)
+			for x in self.match(mysplit[0],use_cache=0):
+				if x==mycpv:
+					continue
+				try:
+					old_counter = long(self.aux_get(x,["COUNTER"])[0])
+					writemsg("COUNTER '%d' '%s'\n" % (old_counter, x),1)
+				except (ValueError, KeyError): # valueError from long(), KeyError from aux_get
+					old_counter = 0
+					writemsg("!!! BAD COUNTER in '%s'\n" % (x), noiselevel=-1)
+				if old_counter > min_counter:
+					min_counter = old_counter
+
+		# We write our new counter value to a new file that gets moved into
+		# place to avoid filesystem corruption.
+		find_counter = ("find '%s' -type f -name COUNTER | " + \
+			"while read f; do echo $(<\"${f}\"); done | " + \
+			"sort -n | tail -n1") % os.path.join(self.root, VDB_PATH)
+		if os.path.exists(cpath):
+			cfile=open(cpath, "r")
+			try:
+				counter=long(cfile.readline())
+			except (ValueError,OverflowError):
+				try:
+					counter = long(commands.getoutput(find_counter).strip())
+					writemsg("!!! COUNTER was corrupted; resetting to value of %d\n" % counter,
+						noiselevel=-1)
+					changed=1
+				except (ValueError,OverflowError):
+					writemsg("!!! COUNTER data is corrupt in pkg db. The values need to be\n",
+						noiselevel=-1)
+					writemsg("!!! corrected/normalized so that portage can operate properly.\n",
+						noiselevel=-1)
+					writemsg("!!! A simple solution is not yet available so try #gentoo on IRC.\n")
+					sys.exit(2)
+			cfile.close()
+		else:
+			try:
+				counter = long(commands.getoutput(find_counter).strip())
+				writemsg("!!! Global counter missing. Regenerated from counter files to: %s\n" % counter,
+					noiselevel=-1)
+			except ValueError: # Value Error for long(), probably others for commands.getoutput
+				writemsg("!!! Initializing global counter.\n", noiselevel=-1)
+				counter=long(0)
+			changed=1
+
+		if counter < min_counter:
+			counter = min_counter+1000
+			changed = 1
+
+		if incrementing or changed:
+
+			#increment counter
+			counter += 1
+			# update new global counter file
+			write_atomic(cpath, str(counter))
+		return counter
+
+class vartree(object):
+	"this tree will scan a var/db/pkg database located at root (passed to init)"
+	def __init__(self, root="/", virtual=None, clone=None, categories=None,
+		settings=None):
+		if clone:
+			self.root       = clone.root[:]
+			self.dbapi      = copy.deepcopy(clone.dbapi)
+			self.populated  = 1
+			self.settings   = config(clone=clone.settings)
+		else:
+			self.root       = root[:]
+			if settings is None:
+				settings = globals()["settings"]
+			self.settings = settings # for key_expand calls
+			if categories is None:
+				categories = settings.categories
+			self.dbapi = vardbapi(self.root, categories=categories,
+				settings=settings, vartree=self)
+			self.populated  = 1
+
+	def zap(self,mycpv):
+		return
+
+	def inject(self,mycpv):
+		return
+
+	def get_provide(self,mycpv):
+		myprovides=[]
+		mylines = None
+		try:
+			mylines, myuse = self.dbapi.aux_get(mycpv, ["PROVIDE","USE"])
+			if mylines:
+				myuse = myuse.split()
+				mylines = flatten(portage_dep.use_reduce(portage_dep.paren_reduce(mylines), uselist=myuse))
+				for myprovide in mylines:
+					mys = catpkgsplit(myprovide)
+					if not mys:
+						mys = myprovide.split("/")
+					myprovides += [mys[0] + "/" + mys[1]]
+			return myprovides
+		except SystemExit, e:
+			raise
+		except Exception, e:
+			mydir = os.path.join(self.root, VDB_PATH, mycpv)
+			writemsg("\nParse Error reading PROVIDE and USE in '%s'\n" % mydir,
+				noiselevel=-1)
+			if mylines:
+				writemsg("Possibly Invalid: '%s'\n" % str(mylines),
+					noiselevel=-1)
+			writemsg("Exception: %s\n\n" % str(e), noiselevel=-1)
+			return []
+
+	def get_all_provides(self):
+		myprovides = {}
+		for node in self.getallcpv():
+			for mykey in self.get_provide(node):
+				if myprovides.has_key(mykey):
+					myprovides[mykey] += [node]
+				else:
+					myprovides[mykey]  = [node]
+		return myprovides
+
+	def dep_bestmatch(self,mydep,use_cache=1):
+		"compatibility method -- all matches, not just visible ones"
+		#mymatch=best(match(dep_expand(mydep,self.dbapi),self.dbapi))
+		mymatch = best(self.dbapi.match(
+			dep_expand(mydep, mydb=self.dbapi, settings=self.settings),
+			use_cache=use_cache))
+		if mymatch is None:
+			return ""
+		else:
+			return mymatch
+
+	def dep_match(self,mydep,use_cache=1):
+		"compatibility method -- we want to see all matches, not just visible ones"
+		#mymatch=match(mydep,self.dbapi)
+		mymatch=self.dbapi.match(mydep,use_cache=use_cache)
+		if mymatch is None:
+			return []
+		else:
+			return mymatch
+
+	def exists_specific(self,cpv):
+		return self.dbapi.cpv_exists(cpv)
+
+	def getallcpv(self):
+		"""temporary function, probably to be renamed --- Gets a list of all
+		category/package-versions installed on the system."""
+		return self.dbapi.cpv_all()
+
+	def getallnodes(self):
+		"""new behavior: these are all *unmasked* nodes.  There may or may not be available
+		masked package for nodes in this nodes list."""
+		return self.dbapi.cp_all()
+
+	def exists_specific_cat(self,cpv,use_cache=1):
+		cpv = key_expand(cpv, mydb=self.dbapi, use_cache=use_cache,
+			settings=self.settings)
+		a=catpkgsplit(cpv)
+		if not a:
+			return 0
+		mylist=listdir(self.root+VDB_PATH+"/"+a[0],EmptyOnError=1)
+		for x in mylist:
+			b=pkgsplit(x)
+			if not b:
+				self.dbapi.invalidentry(self.root+VDB_PATH+"/"+a[0]+"/"+x)
+				continue
+			if a[1]==b[0]:
+				return 1
+		return 0
+
+	def getebuildpath(self,fullpackage):
+		cat,package=fullpackage.split("/")
+		return self.root+VDB_PATH+"/"+fullpackage+"/"+package+".ebuild"
+
+	def getnode(self,mykey,use_cache=1):
+		mykey = key_expand(mykey, mydb=self.dbapi, use_cache=use_cache,
+			settings=self.settings)
+		if not mykey:
+			return []
+		mysplit=mykey.split("/")
+		mydirlist=listdir(self.root+VDB_PATH+"/"+mysplit[0],EmptyOnError=1)
+		returnme=[]
+		for x in mydirlist:
+			mypsplit=pkgsplit(x)
+			if not mypsplit:
+				self.dbapi.invalidentry(self.root+VDB_PATH+"/"+mysplit[0]+"/"+x)
+				continue
+			if mypsplit[0]==mysplit[1]:
+				appendme=[mysplit[0]+"/"+x,[mysplit[0],mypsplit[0],mypsplit[1],mypsplit[2]]]
+				returnme.append(appendme)
+		return returnme
+
+
+	def getslot(self,mycatpkg):
+		"Get a slot for a catpkg; assume it exists."
+		try:
+			return self.dbapi.aux_get(mycatpkg, ["SLOT"])[0]
+		except KeyError:
+			return ""
+
+	def hasnode(self,mykey,use_cache):
+		"""Does the particular node (cat/pkg key) exist?"""
+		mykey = key_expand(mykey, mydb=self.dbapi, use_cache=use_cache,
+			settings=self.settings)
+		mysplit=mykey.split("/")
+		mydirlist=listdir(self.root+VDB_PATH+"/"+mysplit[0],EmptyOnError=1)
+		for x in mydirlist:
+			mypsplit=pkgsplit(x)
+			if not mypsplit:
+				self.dbapi.invalidentry(self.root+VDB_PATH+"/"+mysplit[0]+"/"+x)
+				continue
+			if mypsplit[0]==mysplit[1]:
+				return 1
+		return 0
+
+	def populate(self):
+		self.populated=1
+
+auxdbkeys=[
+  'DEPEND',    'RDEPEND',   'SLOT',      'SRC_URI',
+	'RESTRICT',  'HOMEPAGE',  'LICENSE',   'DESCRIPTION',
+	'KEYWORDS',  'INHERITED', 'IUSE',      'CDEPEND',
+	'PDEPEND',   'PROVIDE', 'EAPI',
+	'UNUSED_01', 'UNUSED_02', 'UNUSED_03', 'UNUSED_04',
+	'UNUSED_05', 'UNUSED_06', 'UNUSED_07',
+	]
+auxdbkeylen=len(auxdbkeys)
+
+def close_portdbapi_caches():
+	for i in portdbapi.portdbapi_instances:
+		i.close_caches()
+
+
+class portdbapi(dbapi):
+	"""this tree will scan a portage directory located at root (passed to init)"""
+	portdbapi_instances = []
+
+	def __init__(self,porttree_root,mysettings=None):
+		portdbapi.portdbapi_instances.append(self)
+
+		if mysettings:
+			self.mysettings = mysettings
+		else:
+			global settings
+			self.mysettings = config(clone=settings)
+		self._categories = set(self.mysettings.categories)
+		# This is strictly for use in aux_get() doebuild calls when metadata
+		# is generated by the depend phase.  It's safest to use a clone for
+		# this purpose because doebuild makes many changes to the config
+		# instance that is passed in.
+		self.doebuild_settings = config(clone=self.mysettings)
+
+		self.manifestVerifyLevel  = None
+		self.manifestVerifier     = None
+		self.manifestCache        = {}    # {location: [stat, md5]}
+		self.manifestMissingCache = []
+
+		if "gpg" in self.mysettings.features:
+			self.manifestVerifyLevel   = portage_gpg.EXISTS
+			if "strict" in self.mysettings.features:
+				self.manifestVerifyLevel = portage_gpg.MARGINAL
+				self.manifestVerifier = portage_gpg.FileChecker(self.mysettings["PORTAGE_GPG_DIR"], "gentoo.gpg", minimumTrust=self.manifestVerifyLevel)
+			elif "severe" in self.mysettings.features:
+				self.manifestVerifyLevel = portage_gpg.TRUSTED
+				self.manifestVerifier = portage_gpg.FileChecker(self.mysettings["PORTAGE_GPG_DIR"], "gentoo.gpg", requireSignedRing=True, minimumTrust=self.manifestVerifyLevel)
+			else:
+				self.manifestVerifier = portage_gpg.FileChecker(self.mysettings["PORTAGE_GPG_DIR"], "gentoo.gpg", minimumTrust=self.manifestVerifyLevel)
+
+		#self.root=settings["PORTDIR"]
+		self.porttree_root = os.path.realpath(porttree_root)
+
+		self.depcachedir = self.mysettings.depcachedir[:]
+
+		self.tmpfs = self.mysettings["PORTAGE_TMPFS"]
+		if self.tmpfs and not os.path.exists(self.tmpfs):
+			self.tmpfs = None
+		if self.tmpfs and not os.access(self.tmpfs, os.W_OK):
+			self.tmpfs = None
+		if self.tmpfs and not os.access(self.tmpfs, os.R_OK):
+			self.tmpfs = None
+
+		self.eclassdb = eclass_cache.cache(self.porttree_root,
+			overlays=self.mysettings["PORTDIR_OVERLAY"].split())
+
+		self.metadbmodule = self.mysettings.load_best_module("portdbapi.metadbmodule")
+
+		#if the portdbapi is "frozen", then we assume that we can cache everything (that no updates to it are happening)
+		self.xcache={}
+		self.frozen=0
+
+		self.porttrees = [self.porttree_root] + \
+			[os.path.realpath(t) for t in self.mysettings["PORTDIR_OVERLAY"].split()]
+		self.auxdbmodule  = self.mysettings.load_best_module("portdbapi.auxdbmodule")
+		self.auxdb        = {}
+		self._init_cache_dirs()
+		# XXX: REMOVE THIS ONCE UNUSED_0 IS YANKED FROM auxdbkeys
+		# ~harring
+		filtered_auxdbkeys = filter(lambda x: not x.startswith("UNUSED_0"), auxdbkeys)
+		if secpass < 1:
+			from cache import metadata_overlay, volatile
+			for x in self.porttrees:
+				db_ro = self.auxdbmodule(self.depcachedir, x,
+					filtered_auxdbkeys, gid=portage_gid, readonly=True)
+				self.auxdb[x] = metadata_overlay.database(
+					self.depcachedir, x, filtered_auxdbkeys,
+					gid=portage_gid, db_rw=volatile.database,
+					db_ro=db_ro)
+		else:
+			for x in self.porttrees:
+				# location, label, auxdbkeys
+				self.auxdb[x] = self.auxdbmodule(
+					self.depcachedir, x, filtered_auxdbkeys, gid=portage_gid)
+		# Selectively cache metadata in order to optimize dep matching.
+		self._aux_cache_keys = set(["EAPI", "KEYWORDS", "SLOT"])
+		self._aux_cache = {}
+
+	def _init_cache_dirs(self):
+		"""Create /var/cache/edb/dep and adjust permissions for the portage
+		group."""
+
+		dirmode  = 02070
+		filemode =   060
+		modemask =    02
+
+		try:
+			for mydir in (self.depcachedir,):
+				if portage_util.ensure_dirs(mydir, gid=portage_gid, mode=dirmode, mask=modemask):
+					writemsg("Adjusting permissions recursively: '%s'\n" % mydir,
+						noiselevel=-1)
+					def onerror(e):
+						raise # bail out on the first error that occurs during recursion
+					if not apply_recursive_permissions(mydir,
+						gid=portage_gid, dirmode=dirmode, dirmask=modemask,
+						filemode=filemode, filemask=modemask, onerror=onerror):
+						raise portage_exception.OperationNotPermitted(
+							"Failed to apply recursive permissions for the portage group.")
+		except portage_exception.PortageException, e:
+			pass
+
+	def close_caches(self):
+		for x in self.auxdb.keys():
+			self.auxdb[x].sync()
+		self.auxdb.clear()
+
+	def flush_cache(self):
+		for x in self.auxdb.values():
+			x.sync()
+
+	def finddigest(self,mycpv):
+		try:
+			mydig   = self.findname2(mycpv)[0]
+			if not mydig:
+				return ""
+			mydigs  = mydig.split("/")[:-1]
+			mydig   = "/".join(mydigs)
+			mysplit = mycpv.split("/")
+		except OSError:
+			return ""
+		return mydig+"/files/digest-"+mysplit[-1]
+
+	def findname(self,mycpv):
+		return self.findname2(mycpv)[0]
+
+	def findname2(self, mycpv, mytree=None):
+		""" 
+		Returns the location of the CPV, and what overlay it was in.
+		Searches overlays first, then PORTDIR; this allows us to return the first
+		matching file.  As opposed to starting in portdir and then doing overlays
+		second, we would have to exhaustively search the overlays until we found
+		the file we wanted.
+		"""
+		if not mycpv:
+			return "",0
+		mysplit=mycpv.split("/")
+		psplit=pkgsplit(mysplit[1])
+
+		if mytree:
+			mytrees = [mytree]
+		else:
+			mytrees = self.porttrees[:]
+			mytrees.reverse()
+		if psplit:
+			for x in mytrees:
+				file=x+"/"+mysplit[0]+"/"+psplit[0]+"/"+mysplit[1]+".ebuild"
+				if os.access(file, os.R_OK):
+					return[file, x]
+		return None, 0
+
+	def aux_get(self, mycpv, mylist, mytree=None):
+		"stub code for returning auxilliary db information, such as SLOT, DEPEND, etc."
+		'input: "sys-apps/foo-1.0",["SLOT","DEPEND","HOMEPAGE"]'
+		'return: ["0",">=sys-libs/bar-1.0","http://www.foo.com"] or raise KeyError if error'
+		cache_me = False
+		if not mytree and not set(mylist).difference(self._aux_cache_keys):
+			aux_cache = self._aux_cache.get(mycpv)
+			if aux_cache is not None:
+				return [aux_cache[x] for x in mylist]
+			cache_me = True
+		global auxdbkeys,auxdbkeylen
+		cat,pkg = mycpv.split("/", 1)
+
+		myebuild, mylocation = self.findname2(mycpv, mytree)
+
+		if not myebuild:
+			writemsg("!!! aux_get(): ebuild path for '%(cpv)s' not specified:\n" % {"cpv":mycpv},
+				noiselevel=1)
+			writemsg("!!!            %s\n" % myebuild, noiselevel=1)
+			raise KeyError(mycpv)
+
+		myManifestPath = "/".join(myebuild.split("/")[:-1])+"/Manifest"
+		if "gpg" in self.mysettings.features:
+			try:
+				mys = portage_gpg.fileStats(myManifestPath)
+				if (myManifestPath in self.manifestCache) and \
+				   (self.manifestCache[myManifestPath] == mys):
+					pass
+				elif self.manifestVerifier:
+					if not self.manifestVerifier.verify(myManifestPath):
+						# Verification failed the desired level.
+						raise portage_exception.UntrustedSignature, "Untrusted Manifest: %(manifest)s" % {"manifest":myManifestPath}
+
+				if ("severe" in self.mysettings.features) and \
+				   (mys != portage_gpg.fileStats(myManifestPath)):
+					raise portage_exception.SecurityViolation, "Manifest changed: %(manifest)s" % {"manifest":myManifestPath}
+
+			except portage_exception.InvalidSignature, e:
+				if ("strict" in self.mysettings.features) or \
+				   ("severe" in self.mysettings.features):
+					raise
+				writemsg("!!! INVALID MANIFEST SIGNATURE DETECTED: %(manifest)s\n" % {"manifest":myManifestPath})
+			except portage_exception.MissingSignature, e:
+				if ("severe" in self.mysettings.features):
+					raise
+				if ("strict" in self.mysettings.features):
+					if myManifestPath not in self.manifestMissingCache:
+						writemsg("!!! WARNING: Missing signature in: %(manifest)s\n" % {"manifest":myManifestPath})
+						self.manifestMissingCache.insert(0,myManifestPath)
+			except (OSError,portage_exception.FileNotFound), e:
+				if ("strict" in self.mysettings.features) or \
+				   ("severe" in self.mysettings.features):
+					raise portage_exception.SecurityViolation, "Error in verification of signatures: %(errormsg)s" % {"errormsg":str(e)}
+				writemsg("!!! Manifest is missing or inaccessable: %(manifest)s\n" % {"manifest":myManifestPath},
+					noiselevel=-1)
+
+
+		if os.access(myebuild, os.R_OK):
+			emtime=os.stat(myebuild)[stat.ST_MTIME]
+		else:
+			writemsg("!!! aux_get(): ebuild for '%(cpv)s' does not exist at:\n" % {"cpv":mycpv},
+				noiselevel=-1)
+			writemsg("!!!            %s\n" % myebuild,
+				noiselevel=-1)
+			raise KeyError
+
+		try:
+			mydata = self.auxdb[mylocation][mycpv]
+			if emtime != long(mydata.get("_mtime_", 0)):
+				doregen = True
+			elif len(mydata.get("_eclasses_", [])) > 0:
+				doregen = not self.eclassdb.is_eclass_data_valid(mydata["_eclasses_"])
+			else:
+				doregen = False
+				
+		except KeyError:
+			doregen = True
+		except CacheError:
+			doregen = True
+			try:				del self.auxdb[mylocation][mycpv]
+			except KeyError:	pass
+
+		writemsg("auxdb is valid: "+str(not doregen)+" "+str(pkg)+"\n", 2)
+
+		if doregen:
+			writemsg("doregen: %s %s\n" % (doregen,mycpv), 2)
+			writemsg("Generating cache entry(0) for: "+str(myebuild)+"\n",1)
+
+			self.doebuild_settings.reset()
+			mydata = {}
+			myret = doebuild(myebuild, "depend",
+				self.doebuild_settings["ROOT"], self.doebuild_settings,
+				dbkey=mydata, tree="porttree", mydbapi=self)
+			if myret != os.EX_OK:
+				raise KeyError(mycpv)
+
+			if "EAPI" not in mydata or not mydata["EAPI"].strip():
+				mydata["EAPI"] = "0"
+
+			if not eapi_is_supported(mydata["EAPI"]):
+				# if newer version, wipe everything and negate eapi
+				eapi = mydata["EAPI"]
+				mydata = {}
+				map(lambda x:mydata.setdefault(x, ""), auxdbkeys)
+				mydata["EAPI"] = "-"+eapi
+
+			if mydata.get("INHERITED", False):
+				mydata["_eclasses_"] = self.eclassdb.get_eclass_data(mydata["INHERITED"].split())
+			else:
+				mydata["_eclasses_"] = {}
+			
+			del mydata["INHERITED"]
+
+			mydata["_mtime_"] = emtime
+
+			self.auxdb[mylocation][mycpv] = mydata
+
+		if not mydata.setdefault("EAPI", "0"):
+			mydata["EAPI"] = "0"
+
+		#finally, we look at our internal cache entry and return the requested data.
+		returnme = []
+		for x in mylist:
+			if x == "INHERITED":
+				returnme.append(' '.join(mydata.get("_eclasses_", {}).keys()))
+			else:
+				returnme.append(mydata.get(x,""))
+
+		if cache_me:
+			aux_cache = {}
+			for x in self._aux_cache_keys:
+				aux_cache[x] = mydata.get(x, "")
+			self._aux_cache[mycpv] = aux_cache
+
+		return returnme
+
+	def getfetchlist(self, mypkg, useflags=None, mysettings=None, all=0, mytree=None):
+		if mysettings is None:
+			mysettings = self.mysettings
+		try:
+			myuris = self.aux_get(mypkg, ["SRC_URI"], mytree=mytree)[0]
+		except KeyError:
+			print red("getfetchlist():")+" aux_get() error reading "+mypkg+"; aborting."
+			sys.exit(1)
+
+		if useflags is None:
+			useflags = mysettings["USE"].split()
+
+		myurilist = portage_dep.paren_reduce(myuris)
+		myurilist = portage_dep.use_reduce(myurilist,uselist=useflags,matchall=all)
+		newuris = flatten(myurilist)
+
+		myfiles = []
+		for x in newuris:
+			mya = os.path.basename(x)
+			if not mya in myfiles:
+				myfiles.append(mya)
+		return [newuris, myfiles]
+
+	def getfetchsizes(self,mypkg,useflags=None,debug=0):
+		# returns a filename:size dictionnary of remaining downloads
+		myebuild = self.findname(mypkg)
+		pkgdir = os.path.dirname(myebuild)
+		mf = Manifest(pkgdir, self.mysettings["DISTDIR"])
+		checksums = mf.getDigests()
+		if not checksums:
+			if debug: print "[empty/missing/bad digest]: "+mypkg
+			return None
+		filesdict={}
+		if useflags is None:
+			myuris, myfiles = self.getfetchlist(mypkg,all=1)
+		else:
+			myuris, myfiles = self.getfetchlist(mypkg,useflags=useflags)
+		#XXX: maybe this should be improved: take partial downloads
+		# into account? check checksums?
+		for myfile in myfiles:
+			if myfile not in checksums:
+				if debug:
+					writemsg("[bad digest]: missing %s for %s\n" % (myfile, mypkg))
+				continue
+			file_path = os.path.join(self.mysettings["DISTDIR"], myfile)
+			mystat = None
+			try:
+				mystat = os.stat(file_path)
+			except OSError, e:
+				pass
+			if mystat is None:
+				existing_size = 0
+			else:
+				existing_size = mystat.st_size
+			remaining_size = int(checksums[myfile]["size"]) - existing_size
+			if remaining_size > 0:
+				# Assume the download is resumable.
+				filesdict[myfile] = remaining_size
+			elif remaining_size < 0:
+				# The existing file is too large and therefore corrupt.
+				filesdict[myfile] = int(checksums[myfile]["size"])
+		return filesdict
+
+	def fetch_check(self, mypkg, useflags=None, mysettings=None, all=False):
+		if not useflags:
+			if mysettings:
+				useflags = mysettings["USE"].split()
+		myuri, myfiles = self.getfetchlist(mypkg, useflags=useflags, mysettings=mysettings, all=all)
+		myebuild = self.findname(mypkg)
+		pkgdir = os.path.dirname(myebuild)
+		mf = Manifest(pkgdir, self.mysettings["DISTDIR"])
+		mysums = mf.getDigests()
+
+		failures = {}
+		for x in myfiles:
+			if not mysums or x not in mysums:
+				ok     = False
+				reason = "digest missing"
+			else:
+				try:
+					ok, reason = portage_checksum.verify_all(
+						os.path.join(self.mysettings["DISTDIR"], x), mysums[x])
+				except portage_exception.FileNotFound, e:
+					ok = False
+					reason = "File Not Found: '%s'" % str(e)
+			if not ok:
+				failures[x] = reason
+		if failures:
+			return False
+		return True
+
+	def getsize(self,mypkg,useflags=None,debug=0):
+		# returns the total size of remaining downloads
+		#
+		# we use getfetchsizes() now, so this function would be obsoleted
+		#
+		filesdict=self.getfetchsizes(mypkg,useflags=useflags,debug=debug)
+		if filesdict is None:
+			return "[empty/missing/bad digest]"
+		mysize=0
+		for myfile in filesdict.keys():
+			mysum+=filesdict[myfile]
+		return mysum
+
+	def cpv_exists(self,mykey):
+		"Tells us whether an actual ebuild exists on disk (no masking)"
+		cps2=mykey.split("/")
+		cps=catpkgsplit(mykey,silent=0)
+		if not cps:
+			#invalid cat/pkg-v
+			return 0
+		if self.findname(cps[0]+"/"+cps2[1]):
+			return 1
+		else:
+			return 0
+
+	def cp_all(self):
+		"returns a list of all keys in our tree"
+		d={}
+		for x in self.mysettings.categories:
+			for oroot in self.porttrees:
+				for y in listdir(oroot+"/"+x,EmptyOnError=1,ignorecvs=1,dirsonly=1):
+					d[x+"/"+y] = None
+		l = d.keys()
+		l.sort()
+		return l
+
+	def p_list(self,mycp):
+		d={}
+		for oroot in self.porttrees:
+			for x in listdir(oroot+"/"+mycp,EmptyOnError=1,ignorecvs=1):
+				if x[-7:]==".ebuild":
+					d[x[:-7]] = None
+		return d.keys()
+
+	def cp_list(self, mycp, use_cache=1, mytree=None):
+		mysplit=mycp.split("/")
+		invalid_category = mysplit[0] not in self._categories
+		d={}
+		if mytree:
+			mytrees = [mytree]
+		else:
+			mytrees = self.porttrees
+		for oroot in mytrees:
+			for x in listdir(oroot+"/"+mycp,EmptyOnError=1,ignorecvs=1):
+				if x.endswith(".ebuild"):
+					pf = x[:-7]
+					ps = pkgsplit(pf)
+					if not ps:
+						writemsg("\nInvalid ebuild name: %s\n" % \
+							os.path.join(oroot, mycp, x), noiselevel=-1)
+						continue
+					d[mysplit[0]+"/"+pf] = None
+		if invalid_category and d:
+			writemsg(("\n!!! '%s' has a category that is not listed in " + \
+				"/etc/portage/categories\n") % mycp, noiselevel=-1)
+			return []
+		return d.keys()
+
+	def freeze(self):
+		for x in ["list-visible","bestmatch-visible","match-visible","match-all"]:
+			self.xcache[x]={}
+		self.frozen=1
+
+	def melt(self):
+		self.xcache={}
+		self.frozen=0
+
+	def xmatch(self,level,origdep,mydep=None,mykey=None,mylist=None):
+		"caching match function; very trick stuff"
+		#if no updates are being made to the tree, we can consult our xcache...
+		if self.frozen:
+			try:
+				return self.xcache[level][origdep][:]
+			except KeyError:
+				pass
+
+		if not mydep:
+			#this stuff only runs on first call of xmatch()
+			#create mydep, mykey from origdep
+			mydep = dep_expand(origdep, mydb=self, settings=self.mysettings)
+			mykey=dep_getkey(mydep)
+
+		if level=="list-visible":
+			#a list of all visible packages, not called directly (just by xmatch())
+			#myval=self.visible(self.cp_list(mykey))
+			myval=self.gvisible(self.visible(self.cp_list(mykey)))
+		elif level=="bestmatch-visible":
+			#dep match -- best match of all visible packages
+			myval=best(self.xmatch("match-visible",None,mydep=mydep,mykey=mykey))
+			#get all visible matches (from xmatch()), then choose the best one
+		elif level=="bestmatch-list":
+			#dep match -- find best match but restrict search to sublist
+			myval=best(match_from_list(mydep,mylist))
+			#no point is calling xmatch again since we're not caching list deps
+		elif level=="match-list":
+			#dep match -- find all matches but restrict search to sublist (used in 2nd half of visible())
+			myval=match_from_list(mydep,mylist)
+		elif level=="match-visible":
+			#dep match -- find all visible matches
+			myval = match_from_list(mydep,
+				self.xmatch("list-visible", mykey, mydep=mykey, mykey=mykey))
+			#get all visible packages, then get the matching ones
+		elif level=="match-all":
+			#match *all* visible *and* masked packages
+			myval=match_from_list(mydep,self.cp_list(mykey))
+		else:
+			print "ERROR: xmatch doesn't handle",level,"query!"
+			raise KeyError
+		myslot = portage_dep.dep_getslot(mydep)
+		if myslot is not None:
+			slotmatches = []
+			for cpv in myval:
+				try:
+					if self.aux_get(cpv, ["SLOT"])[0] == myslot:
+						slotmatches.append(cpv)
+				except KeyError:
+					pass # ebuild masked by corruption
+			myval = slotmatches
+		if self.frozen and (level not in ["match-list","bestmatch-list"]):
+			self.xcache[level][mydep]=myval
+			if origdep and origdep != mydep:
+				self.xcache[level][origdep] = myval
+		return myval[:]
+
+	def match(self,mydep,use_cache=1):
+		return self.xmatch("match-visible",mydep)
+
+	def visible(self,mylist):
+		"""two functions in one.  Accepts a list of cpv values and uses the package.mask *and*
+		packages file to remove invisible entries, returning remaining items.  This function assumes
+		that all entries in mylist have the same category and package name."""
+		if (mylist is None) or (len(mylist)==0):
+			return []
+		newlist=mylist[:]
+		#first, we mask out packages in the package.mask file
+		mykey=newlist[0]
+		cpv=catpkgsplit(mykey)
+		if not cpv:
+			#invalid cat/pkg-v
+			print "visible(): invalid cat/pkg-v:",mykey
+			return []
+		mycp=cpv[0]+"/"+cpv[1]
+		maskdict=self.mysettings.pmaskdict
+		unmaskdict=self.mysettings.punmaskdict
+		if maskdict.has_key(mycp):
+			for x in maskdict[mycp]:
+				mymatches=self.xmatch("match-all",x)
+				if mymatches is None:
+					#error in package.mask file; print warning and continue:
+					print "visible(): package.mask entry \""+x+"\" is invalid, ignoring..."
+					continue
+				for y in mymatches:
+					unmask=0
+					if unmaskdict.has_key(mycp):
+						for z in unmaskdict[mycp]:
+							mymatches_unmask=self.xmatch("match-all",z)
+							if y in mymatches_unmask:
+								unmask=1
+								break
+					if unmask==0:
+						try:
+							newlist.remove(y)
+						except ValueError:
+							pass
+
+		revmaskdict=self.mysettings.prevmaskdict
+		if revmaskdict.has_key(mycp):
+			for x in revmaskdict[mycp]:
+				#important: only match against the still-unmasked entries...
+				#notice how we pass "newlist" to the xmatch() call below....
+				#Without this, ~ deps in the packages files are broken.
+				mymatches=self.xmatch("match-list",x,mylist=newlist)
+				if mymatches is None:
+					#error in packages file; print warning and continue:
+					print "emerge: visible(): profile packages entry \""+x+"\" is invalid, ignoring..."
+					continue
+				pos=0
+				while pos<len(newlist):
+					if newlist[pos] not in mymatches:
+						del newlist[pos]
+					else:
+						pos += 1
+		return newlist
+
+	def gvisible(self,mylist):
+		"strip out group-masked (not in current group) entries"
+
+		if mylist is None:
+			return []
+		newlist=[]
+
+		accept_keywords = self.mysettings["ACCEPT_KEYWORDS"].split()
+		pkgdict = self.mysettings.pkeywordsdict
+		for mycpv in mylist:
+			try:
+				keys, eapi = self.aux_get(mycpv, ["KEYWORDS", "EAPI"])
+			except KeyError:
+				continue
+			except portage_exception.PortageException, e:
+				writemsg("!!! Error: aux_get('%s', ['KEYWORDS', 'EAPI'])\n" % \
+					mycpv, noiselevel=-1)
+				writemsg("!!! %s\n" % str(e), noiselevel=-1)
+				del e
+				continue
+			mygroups=keys.split()
+			# Repoman may modify this attribute as necessary.
+			pgroups = accept_keywords[:]
+			match=0
+			cp = dep_getkey(mycpv)
+			if pkgdict.has_key(cp):
+				matches = match_to_list(mycpv, pkgdict[cp].keys())
+				for atom in matches:
+					pgroups.extend(pkgdict[cp][atom])
+				if matches:
+					inc_pgroups = []
+					for x in pgroups:
+						# The -* special case should be removed once the tree 
+						# is clean of KEYWORDS=-* crap
+						if x != "-*" and x.startswith("-"):
+							try:
+								inc_pgroups.remove(x[1:])
+							except ValueError:
+								pass
+						if x not in inc_pgroups:
+							inc_pgroups.append(x)
+					pgroups = inc_pgroups
+					del inc_pgroups
+			hasstable = False
+			hastesting = False
+			for gp in mygroups:
+				if gp=="*":
+					writemsg("--- WARNING: Package '%s' uses '*' keyword.\n" % mycpv,
+						noiselevel=-1)
+					match=1
+					break
+				elif gp in pgroups:
+					match=1
+					break
+				elif gp[0] == "~":
+					hastesting = True
+				elif gp[0] != "-":
+					hasstable = True
+			if not match and ((hastesting and "~*" in pgroups) or (hasstable and "*" in pgroups) or "**" in pgroups):
+				match=1
+			if match and eapi_is_supported(eapi):
+				newlist.append(mycpv)
+		return newlist
+
+class binarytree(object):
+	"this tree scans for a list of all packages available in PKGDIR"
+	def __init__(self, root, pkgdir, virtual=None, settings=None, clone=None):
+		if clone:
+			# XXX This isn't cloning. It's an instance of the same thing.
+			self.root=clone.root
+			self.pkgdir=clone.pkgdir
+			self.dbapi=clone.dbapi
+			self.populated=clone.populated
+			self.tree=clone.tree
+			self.remotepkgs=clone.remotepkgs
+			self.invalids=clone.invalids
+			self.settings = clone.settings
+		else:
+			self.root=root
+			#self.pkgdir=settings["PKGDIR"]
+			self.pkgdir = normalize_path(pkgdir)
+			self.dbapi = bindbapi(self, settings=settings)
+			self.populated=0
+			self.tree={}
+			self.remotepkgs={}
+			self.invalids=[]
+			self.settings = settings
+			self._pkg_paths = {}
+
+	def move_ent(self,mylist):
+		if not self.populated:
+			self.populate()
+		origcp=mylist[1]
+		newcp=mylist[2]
+		# sanity check
+		for cp in [origcp,newcp]:
+			if not (isvalidatom(cp) and isjustname(cp)):
+				raise portage_exception.InvalidPackageName(cp)
+		origcat = origcp.split("/")[0]
+		mynewcat=newcp.split("/")[0]
+		origmatches=self.dbapi.cp_list(origcp)
+		if not origmatches:
+			return
+		for mycpv in origmatches:
+
+			mycpsplit=catpkgsplit(mycpv)
+			mynewcpv=newcp+"-"+mycpsplit[2]
+			if mycpsplit[3]!="r0":
+				mynewcpv += "-"+mycpsplit[3]
+			myoldpkg=mycpv.split("/")[1]
+			mynewpkg=mynewcpv.split("/")[1]
+
+			if (mynewpkg != myoldpkg) and os.path.exists(self.getname(mynewcpv)):
+				writemsg("!!! Cannot update binary: Destination exists.\n",
+					noiselevel=-1)
+				writemsg("!!! "+mycpv+" -> "+mynewcpv+"\n", noiselevel=-1)
+				continue
+
+			tbz2path=self.getname(mycpv)
+			if os.path.exists(tbz2path) and not os.access(tbz2path,os.W_OK):
+				writemsg("!!! Cannot update readonly binary: "+mycpv+"\n",
+					noiselevel=-1)
+				continue
+
+			#print ">>> Updating data in:",mycpv
+			writemsg_stdout("%")
+			mytbz2 = xpak.tbz2(tbz2path)
+			mydata = mytbz2.get_data()
+			updated_items = update_dbentries([mylist], mydata)
+			mydata.update(updated_items)
+			mydata["CATEGORY"] = mynewcat+"\n"
+			if mynewpkg != myoldpkg:
+				mydata[mynewpkg+".ebuild"] = mydata[myoldpkg+".ebuild"]
+				del mydata[myoldpkg+".ebuild"]
+				mydata["PF"] = mynewpkg + "\n"
+			mytbz2.recompose_mem(xpak.xpak_mem(mydata))
+
+			self.dbapi.cpv_remove(mycpv)
+			del self._pkg_paths[mycpv]
+			new_path = self.getname(mynewcpv)
+			self._pkg_paths[mynewcpv] = os.path.join(
+				*new_path.split(os.path.sep)[-2:])
+			if new_path != mytbz2:
+				try:
+					os.makedirs(os.path.dirname(new_path))
+				except OSError, e:
+					if e.errno != errno.EEXIST:
+						raise
+					del e
+				os.rename(tbz2path, new_path)
+				self._remove_symlink(mycpv)
+				if new_path.split(os.path.sep)[-2] == "All":
+					self._create_symlink(mynewcpv)
+			self.dbapi.cpv_inject(mynewcpv)
+
+		return 1
+
+	def _remove_symlink(self, cpv):
+		"""Remove a ${PKGDIR}/${CATEGORY}/${PF}.tbz2 symlink and also remove
+		the ${PKGDIR}/${CATEGORY} directory if empty.  The file will not be
+		removed if os.path.islink() returns False."""
+		mycat, mypkg = catsplit(cpv)
+		mylink = os.path.join(self.pkgdir, mycat, mypkg + ".tbz2")
+		if os.path.islink(mylink):
+			"""Only remove it if it's really a link so that this method never
+			removes a real package that was placed here to avoid a collision."""
+			os.unlink(mylink)
+		try:
+			os.rmdir(os.path.join(self.pkgdir, mycat))
+		except OSError, e:
+			if e.errno not in (errno.ENOENT,
+				errno.ENOTEMPTY, errno.EEXIST):
+				raise
+			del e
+
+	def _create_symlink(self, cpv):
+		"""Create a ${PKGDIR}/${CATEGORY}/${PF}.tbz2 symlink (and
+		${PKGDIR}/${CATEGORY} directory, if necessary).  Any file that may
+		exist in the location of the symlink will first be removed."""
+		mycat, mypkg = catsplit(cpv)
+		full_path = os.path.join(self.pkgdir, mycat, mypkg + ".tbz2")
+		try:
+			os.makedirs(os.path.dirname(full_path))
+		except OSError, e:
+			if e.errno != errno.EEXIST:
+				raise
+			del e
+		try:
+			os.unlink(full_path)
+		except OSError, e:
+			if e.errno != errno.ENOENT:
+				raise
+			del e
+		os.symlink(os.path.join("..", "All", mypkg + ".tbz2"), full_path)
+
+	def move_slot_ent(self, mylist):
+		if not self.populated:
+			self.populate()
+		pkg=mylist[1]
+		origslot=mylist[2]
+		newslot=mylist[3]
+		
+		if not isvalidatom(pkg):
+			raise portage_exception.InvalidAtom(pkg)
+		
+		origmatches=self.dbapi.match(pkg)
+		if not origmatches:
+			return
+		for mycpv in origmatches:
+			mycpsplit=catpkgsplit(mycpv)
+			myoldpkg=mycpv.split("/")[1]
+			tbz2path=self.getname(mycpv)
+			if os.path.exists(tbz2path) and not os.access(tbz2path,os.W_OK):
+				writemsg("!!! Cannot update readonly binary: "+mycpv+"\n",
+					noiselevel=-1)
+				continue
+
+			#print ">>> Updating data in:",mycpv
+			mytbz2 = xpak.tbz2(tbz2path)
+			mydata = mytbz2.get_data()
+
+			slot = mydata["SLOT"]
+			if (not slot):
+				continue
+
+			if (slot[0]!=origslot):
+				continue
+
+			writemsg_stdout("S")
+			mydata["SLOT"] = newslot+"\n"
+			mytbz2.recompose_mem(xpak.xpak_mem(mydata))
+		return 1
+
+	def update_ents(self, update_iter):
+		if len(update_iter) == 0:
+			return
+		if not self.populated:
+			self.populate()
+
+		for mycpv in self.dbapi.cp_all():
+			tbz2path=self.getname(mycpv)
+			if os.path.exists(tbz2path) and not os.access(tbz2path,os.W_OK):
+				writemsg("!!! Cannot update readonly binary: "+mycpv+"\n",
+					noiselevel=-1)
+				continue
+			#print ">>> Updating binary data:",mycpv
+			writemsg_stdout("*")
+			mytbz2 = xpak.tbz2(tbz2path)
+			mydata = mytbz2.get_data()
+			updated_items = update_dbentries(update_iter, mydata)
+			if len(updated_items) > 0:
+				mydata.update(updated_items)
+				mytbz2.recompose_mem(xpak.xpak_mem(mydata))
+		return 1
+
+	def prevent_collision(self, cpv):
+		"""Make sure that the file location ${PKGDIR}/All/${PF}.tbz2 is safe to
+		use for a given cpv.  If a collision will occur with an existing
+		package from another category, the existing package will be bumped to
+		${PKGDIR}/${CATEGORY}/${PF}.tbz2 so that both can coexist."""
+		if not self.populated:
+			# Try to avoid the population routine when possible, so that
+			# FEATURES=buildpkg doesn't always force population.
+			mycat, mypkg = catsplit(cpv)
+			myfile = mypkg + ".tbz2"
+			full_path = os.path.join(self.pkgdir, "All", myfile)
+			if not os.path.exists(full_path):
+				return
+			tbz2_cat = xpak.tbz2(full_path).getfile("CATEGORY")
+			if tbz2_cat and tbz2_cat.strip() == mycat:
+				return
+		full_path = self.getname(cpv)
+		if "All" == full_path.split(os.path.sep)[-2]:
+			return
+		"""Move a colliding package if it exists.  Code below this point only
+		executes in rare cases."""
+		mycat, mypkg = catsplit(cpv)
+		myfile = mypkg + ".tbz2"
+		mypath = os.path.join("All", myfile)
+		dest_path = os.path.join(self.pkgdir, mypath)
+		if os.path.exists(dest_path):
+			# For invalid packages, other_cat could be None.
+			other_cat = xpak.tbz2(dest_path).getfile("CATEGORY")
+			if other_cat:
+				other_cat = other_cat.strip()
+				self._move_from_all(other_cat + "/" + mypkg)
+		"""The file may or may not exist. Move it if necessary and update
+		internal state for future calls to getname()."""
+		self._move_to_all(cpv)
+
+	def _move_to_all(self, cpv):
+		"""If the file exists, move it.  Whether or not it exists, update state
+		for future getname() calls."""
+		mycat , mypkg = catsplit(cpv)
+		myfile = mypkg + ".tbz2"
+		src_path = os.path.join(self.pkgdir, mycat, myfile)
+		try:
+			mystat = os.lstat(src_path)
+		except OSError, e:
+			mystat = None
+		if mystat and stat.S_ISREG(mystat.st_mode):
+			try:
+				os.makedirs(os.path.join(self.pkgdir, "All"))
+			except OSError, e:
+				if e.errno != errno.EEXIST:
+					raise
+				del e
+			os.rename(src_path, os.path.join(self.pkgdir, "All", myfile))
+			self._create_symlink(cpv)
+		self._pkg_paths[cpv] = os.path.join("All", myfile)
+
+	def _move_from_all(self, cpv):
+		"""Move a package from ${PKGDIR}/All/${PF}.tbz2 to
+		${PKGDIR}/${CATEGORY}/${PF}.tbz2 and update state from getname calls."""
+		self._remove_symlink(cpv)
+		mycat , mypkg = catsplit(cpv)
+		myfile = mypkg + ".tbz2"
+		mypath = os.path.join(mycat, myfile)
+		dest_path = os.path.join(self.pkgdir, mypath)
+		try:
+			os.makedirs(os.path.dirname(dest_path))
+		except OSError, e:
+			if e.errno != errno.EEXIST:
+				raise
+			del e
+		os.rename(os.path.join(self.pkgdir, "All", myfile), dest_path)
+		self._pkg_paths[cpv] = mypath
+
+	def populate(self, getbinpkgs=0,getbinpkgsonly=0):
+		"populates the binarytree"
+		if (not os.path.isdir(self.pkgdir) and not getbinpkgs):
+			return 0
+		if (not os.path.isdir(self.pkgdir+"/All") and not getbinpkgs):
+			return 0
+
+		categories = set(self.settings.categories)
+
+		if not getbinpkgsonly:
+			pkg_paths = {}
+			dirs = listdir(self.pkgdir, dirsonly=True, EmptyOnError=True)
+			if "All" in dirs:
+				dirs.remove("All")
+			dirs.sort()
+			dirs.insert(0, "All")
+			for mydir in dirs:
+				for myfile in listdir(os.path.join(self.pkgdir, mydir)):
+					if not myfile.endswith(".tbz2"):
+						continue
+					mypath = os.path.join(mydir, myfile)
+					full_path = os.path.join(self.pkgdir, mypath)
+					if os.path.islink(full_path):
+						continue
+					mytbz2 = xpak.tbz2(full_path)
+					# For invalid packages, mycat could be None.
+					mycat = mytbz2.getfile("CATEGORY")
+					mypf = mytbz2.getfile("PF")
+					mypkg = myfile[:-5]
+					if not mycat or not mypf:
+						#old-style or corrupt package
+						writemsg("!!! Invalid binary package: '%s'\n" % full_path,
+							noiselevel=-1)
+						writemsg("!!! This binary package is not " + \
+							"recoverable and should be deleted.\n",
+							noiselevel=-1)
+						self.invalids.append(mypkg)
+						continue
+					mycat = mycat.strip()
+					if mycat != mydir and mydir != "All":
+						continue
+					if mypkg != mypf.strip():
+						continue
+					mycpv = mycat + "/" + mypkg
+					if mycpv in pkg_paths:
+						# All is first, so it's preferred.
+						continue
+					if mycat not in categories:
+						writemsg(("!!! Binary package has an " + \
+							"unrecognized category: '%s'\n") % full_path,
+							noiselevel=-1)
+						writemsg(("!!! '%s' has a category that is not" + \
+							" listed in /etc/portage/categories\n") % mycpv,
+							noiselevel=-1)
+						continue
+					pkg_paths[mycpv] = mypath
+					self.dbapi.cpv_inject(mycpv)
+			self._pkg_paths = pkg_paths
+
+		if getbinpkgs and not self.settings["PORTAGE_BINHOST"]:
+			writemsg(red("!!! PORTAGE_BINHOST unset, but use is requested.\n"),
+				noiselevel=-1)
+
+		if getbinpkgs and \
+			self.settings["PORTAGE_BINHOST"] and not self.remotepkgs:
+			try:
+				chunk_size = long(self.settings["PORTAGE_BINHOST_CHUNKSIZE"])
+				if chunk_size < 8:
+					chunk_size = 8
+			except (ValueError, KeyError):
+				chunk_size = 3000
+
+			writemsg(green("Fetching binary packages info...\n"))
+			self.remotepkgs = getbinpkg.dir_get_metadata(
+				self.settings["PORTAGE_BINHOST"], chunk_size=chunk_size)
+			writemsg(green("  -- DONE!\n\n"))
+
+			for mypkg in self.remotepkgs.keys():
+				if not self.remotepkgs[mypkg].has_key("CATEGORY"):
+					#old-style or corrupt package
+					writemsg("!!! Invalid remote binary package: "+mypkg+"\n",
+						noiselevel=-1)
+					del self.remotepkgs[mypkg]
+					continue
+				mycat=self.remotepkgs[mypkg]["CATEGORY"].strip()
+				fullpkg=mycat+"/"+mypkg[:-5]
+				if mycat not in categories:
+					writemsg(("!!! Remote binary package has an " + \
+						"unrecognized category: '%s'\n") % fullpkg,
+						noiselevel=-1)
+					writemsg(("!!! '%s' has a category that is not" + \
+						" listed in /etc/portage/categories\n") % fullpkg,
+						noiselevel=-1)
+					continue
+				mykey=dep_getkey(fullpkg)
+				try:
+					# invalid tbz2's can hurt things.
+					#print "cpv_inject("+str(fullpkg)+")"
+					self.dbapi.cpv_inject(fullpkg)
+					#print "  -- Injected"
+				except SystemExit, e:
+					raise
+				except:
+					writemsg("!!! Failed to inject remote binary package:"+str(fullpkg)+"\n",
+						noiselevel=-1)
+					del self.remotepkgs[mypkg]
+					continue
+		self.populated=1
+
+	def inject(self,cpv):
+		return self.dbapi.cpv_inject(cpv)
+
+	def exists_specific(self,cpv):
+		if not self.populated:
+			self.populate()
+		return self.dbapi.match(
+			dep_expand("="+cpv, mydb=self.dbapi, settings=self.settings))
+
+	def dep_bestmatch(self,mydep):
+		"compatibility method -- all matches, not just visible ones"
+		if not self.populated:
+			self.populate()
+		writemsg("\n\n", 1)
+		writemsg("mydep: %s\n" % mydep, 1)
+		mydep = dep_expand(mydep, mydb=self.dbapi, settings=self.settings)
+		writemsg("mydep: %s\n" % mydep, 1)
+		mykey=dep_getkey(mydep)
+		writemsg("mykey: %s\n" % mykey, 1)
+		mymatch=best(match_from_list(mydep,self.dbapi.cp_list(mykey)))
+		writemsg("mymatch: %s\n" % mymatch, 1)
+		if mymatch is None:
+			return ""
+		return mymatch
+
+	def getname(self,pkgname):
+		"""Returns a file location for this package.  The default location is
+		${PKGDIR}/All/${PF}.tbz2, but will be ${PKGDIR}/${CATEGORY}/${PF}.tbz2
+		in the rare event of a collision.  The prevent_collision() method can
+		be called to ensure that ${PKGDIR}/All/${PF}.tbz2 is available for a
+		specific cpv."""
+		if not self.populated:
+			self.populate()
+		mycpv = pkgname
+		mypath = self._pkg_paths.get(mycpv, None)
+		if mypath:
+			return os.path.join(self.pkgdir, mypath)
+		mycat, mypkg = catsplit(mycpv)
+		mypath = os.path.join("All", mypkg + ".tbz2")
+		if mypath in self._pkg_paths.values():
+			mypath = os.path.join(mycat, mypkg + ".tbz2")
+		self._pkg_paths[mycpv] = mypath # cache for future lookups
+		return os.path.join(self.pkgdir, mypath)
+
+	def isremote(self,pkgname):
+		"Returns true if the package is kept remotely."
+		mysplit=pkgname.split("/")
+		remote = (not os.path.exists(self.getname(pkgname))) and self.remotepkgs.has_key(mysplit[1]+".tbz2")
+		return remote
+
+	def get_use(self,pkgname):
+		mysplit=pkgname.split("/")
+		if self.isremote(pkgname):
+			return self.remotepkgs[mysplit[1]+".tbz2"]["USE"][:].split()
+		tbz2=xpak.tbz2(self.getname(pkgname))
+		return tbz2.getfile("USE").split()
+
+	def gettbz2(self,pkgname):
+		"fetches the package from a remote site, if necessary."
+		print "Fetching '"+str(pkgname)+"'"
+		mysplit  = pkgname.split("/")
+		tbz2name = mysplit[1]+".tbz2"
+		if not self.isremote(pkgname):
+			if (tbz2name not in self.invalids):
+				return
+			else:
+				writemsg("Resuming download of this tbz2, but it is possible that it is corrupt.\n",
+					noiselevel=-1)
+		mydest = self.pkgdir+"/All/"
+		try:
+			os.makedirs(mydest, 0775)
+		except (OSError, IOError):
+			pass
+		return getbinpkg.file_get(
+			self.settings["PORTAGE_BINHOST"] + "/" + tbz2name,
+			mydest, fcmd=self.settings["RESUMECOMMAND"])
+
+	def getslot(self,mycatpkg):
+		"Get a slot for a catpkg; assume it exists."
+		myslot = ""
+		try:
+			myslot=self.dbapi.aux_get(mycatpkg,["SLOT"])[0]
+		except SystemExit, e:
+			raise
+		except Exception, e:
+			pass
+		return myslot
+
+class dblink:
+	"""
+	This class provides an interface to the installed package database
+	At present this is implemented as a text backend in /var/db/pkg.
+	"""
+	def __init__(self, cat, pkg, myroot, mysettings, treetype=None,
+		vartree=None):
+		"""
+		Creates a DBlink object for a given CPV.
+		The given CPV may not be present in the database already.
+		
+		@param cat: Category
+		@type cat: String
+		@param pkg: Package (PV)
+		@type pkg: String
+		@param myroot: Typically ${ROOT}
+		@type myroot: String (Path)
+		@param mysettings: Typically portage.config
+		@type mysettings: An instance of portage.config
+		@param treetype: one of ['porttree','bintree','vartree']
+		@type treetype: String
+		@param vartree: an instance of vartree corresponding to myroot.
+		@type vartree: vartree
+		"""
+		
+		self.cat     = cat
+		self.pkg     = pkg
+		self.mycpv   = self.cat+"/"+self.pkg
+		self.mysplit = pkgsplit(self.mycpv)
+		self.treetype = treetype
+		if vartree is None:
+			global db
+			vartree = db[myroot]["vartree"]
+		self.vartree = vartree
+
+		self.dbroot   = normalize_path(os.path.join(myroot, VDB_PATH))
+		self.dbcatdir = self.dbroot+"/"+cat
+		self.dbpkgdir = self.dbcatdir+"/"+pkg
+		self.dbtmpdir = self.dbcatdir+"/-MERGING-"+pkg
+		self.dbdir    = self.dbpkgdir
+
+		self._lock_vdb = None
+
+		self.settings = mysettings
+		if self.settings==1:
+			raise ValueError
+
+		self.myroot=myroot
+		protect_obj = portage_util.ConfigProtect(myroot,
+			mysettings.get("CONFIG_PROTECT","").split(),
+			mysettings.get("CONFIG_PROTECT_MASK","").split())
+		self.updateprotect = protect_obj.updateprotect
+		self._config_protect = protect_obj
+		self._installed_instance = None
+		self.contentscache=[]
+		self._contents_inodes = None
+
+	def lockdb(self):
+		if self._lock_vdb:
+			raise AssertionError("Lock already held.")
+		# At least the parent needs to exist for the lock file.
+		portage_util.ensure_dirs(self.dbroot)
+		self._lock_vdb = portage_locks.lockdir(self.dbroot)
+
+	def unlockdb(self):
+		if self._lock_vdb:
+			portage_locks.unlockdir(self._lock_vdb)
+			self._lock_vdb = None
+
+	def getpath(self):
+		"return path to location of db information (for >>> informational display)"
+		return self.dbdir
+
+	def exists(self):
+		"does the db entry exist?  boolean."
+		return os.path.exists(self.dbdir)
+
+	def create(self):
+		"create the skeleton db directory structure.  No contents, virtuals, provides or anything.  Also will create /var/db/pkg if necessary."
+		"""
+		This function should never get called (there is no reason to use it).
+		"""
+		# XXXXX Delete this eventually
+		raise Exception, "This is bad. Don't use it."
+		if not os.path.exists(self.dbdir):
+			os.makedirs(self.dbdir)
+
+	def delete(self):
+		"""
+		Remove this entry from the database
+		"""
+		if not os.path.exists(self.dbdir):
+			return
+		try:
+			for x in listdir(self.dbdir):
+				os.unlink(self.dbdir+"/"+x)
+			os.rmdir(self.dbdir)
+		except OSError, e:
+			print "!!! Unable to remove db entry for this package."
+			print "!!! It is possible that a directory is in this one. Portage will still"
+			print "!!! register this package as installed as long as this directory exists."
+			print "!!! You may delete this directory with 'rm -Rf "+self.dbdir+"'"
+			print "!!! "+str(e)
+			print
+			sys.exit(1)
+
+	def clearcontents(self):
+		"""
+		For a given db entry (self), erase the CONTENTS values.
+		"""
+		if os.path.exists(self.dbdir+"/CONTENTS"):
+			os.unlink(self.dbdir+"/CONTENTS")
+
+	def getcontents(self):
+		"""
+		Get the installed files of a given package (aka what that package installed)
+		"""
+		if not os.path.exists(self.dbdir+"/CONTENTS"):
+			return None
+		if self.contentscache != []:
+			return self.contentscache
+		pkgfiles={}
+		myc=open(self.dbdir+"/CONTENTS","r")
+		mylines=myc.readlines()
+		myc.close()
+		null_byte = "\0"
+		contents_file = os.path.join(self.dbdir, "CONTENTS")
+		pos = 0
+		for line in mylines:
+			pos += 1
+			if null_byte in line:
+				# Null bytes are a common indication of corruption.
+				writemsg("!!! Null byte found in contents " + \
+					"file, line %d: '%s'\n" % (pos, contents_file),
+					noiselevel=-1)
+				continue
+			mydat = line.split()
+			# we do this so we can remove from non-root filesystems
+			# (use the ROOT var to allow maintenance on other partitions)
+			try:
+				mydat[1] = normalize_path(os.path.join(
+					self.myroot, mydat[1].lstrip(os.path.sep)))
+				if mydat[0]=="obj":
+					#format: type, mtime, md5sum
+					pkgfiles[" ".join(mydat[1:-2])]=[mydat[0], mydat[-1], mydat[-2]]
+				elif mydat[0]=="dir":
+					#format: type
+					pkgfiles[" ".join(mydat[1:])]=[mydat[0] ]
+				elif mydat[0]=="sym":
+					#format: type, mtime, dest
+					x=len(mydat)-1
+					if (x >= 13) and (mydat[-1][-1]==')'): # Old/Broken symlink entry
+						mydat = mydat[:-10]+[mydat[-10:][stat.ST_MTIME][:-1]]
+						writemsg("FIXED SYMLINK LINE: %s\n" % mydat, 1)
+						x=len(mydat)-1
+					splitter=-1
+					while(x>=0):
+						if mydat[x]=="->":
+							splitter=x
+							break
+						x=x-1
+					if splitter==-1:
+						return None
+					pkgfiles[" ".join(mydat[1:splitter])]=[mydat[0], mydat[-1], " ".join(mydat[(splitter+1):-1])]
+				elif mydat[0]=="dev":
+					#format: type
+					pkgfiles[" ".join(mydat[1:])]=[mydat[0] ]
+				elif mydat[0]=="fif":
+					#format: type
+					pkgfiles[" ".join(mydat[1:])]=[mydat[0]]
+				else:
+					return None
+			except (KeyError,IndexError):
+				print "portage: CONTENTS line",pos,"corrupt!"
+		self.contentscache=pkgfiles
+		return pkgfiles
+
+	def unmerge(self, pkgfiles=None, trimworld=1, cleanup=1,
+		ldpath_mtimes=None):
+		"""
+		Calls prerm
+		Unmerges a given package (CPV)
+		calls postrm
+		calls cleanrm
+		calls env_update
+		
+		@param pkgfiles: files to unmerge (generally self.getcontents() )
+		@type pkgfiles: Dictionary
+		@param trimworld: Remove CPV from world file if True, not if False
+		@type trimworld: Boolean
+		@param cleanup: cleanup to pass to doebuild (see doebuild)
+		@type cleanup: Boolean
+		@param ldpath_mtimes: mtimes to pass to env_update (see env_update)
+		@type ldpath_mtimes: Dictionary
+		@rtype: Integer
+		@returns:
+		1. os.EX_OK if everything went well.
+		2. return code of the failed phase (for prerm, postrm, cleanrm)
+		
+		Notes:
+		The caller must ensure that lockdb() and unlockdb() are called
+		before and after this method.
+		"""
+
+		contents = self.getcontents()
+		# Now, don't assume that the name of the ebuild is the same as the
+		# name of the dir; the package may have been moved.
+		myebuildpath = None
+		mystuff = listdir(self.dbdir, EmptyOnError=1)
+		for x in mystuff:
+			if x.endswith(".ebuild"):
+				myebuildpath = os.path.join(self.dbdir, self.pkg + ".ebuild")
+				if x[:-7] != self.pkg:
+					# Clean up after vardbapi.move_ent() breakage in
+					# portage versions before 2.1.2
+					os.rename(os.path.join(self.dbdir, x), myebuildpath)
+					write_atomic(os.path.join(self.dbdir, "PF"), self.pkg+"\n")
+				break
+
+		self.settings.load_infodir(self.dbdir)
+		if myebuildpath:
+			try:
+				doebuild_environment(myebuildpath, "prerm", self.myroot,
+					self.settings, 0, 0, self.vartree.dbapi)
+			except portage_exception.UnsupportedAPIException, e:
+				# Sometimes this happens due to corruption of the EAPI file.
+				writemsg("!!! FAILED prerm: %s\n" % \
+					os.path.join(self.dbdir, "EAPI"), noiselevel=-1)
+				writemsg("%s\n" % str(e), noiselevel=-1)
+				return 1
+			catdir = os.path.dirname(self.settings["PORTAGE_BUILDDIR"])
+			portage_util.ensure_dirs(os.path.dirname(catdir),
+				uid=portage_uid, gid=portage_gid, mode=070, mask=0)
+		builddir_lock = None
+		catdir_lock = None
+		try:
+			if myebuildpath:
+				catdir_lock = portage_locks.lockdir(catdir)
+				portage_util.ensure_dirs(catdir,
+					uid=portage_uid, gid=portage_gid,
+					mode=070, mask=0)
+				builddir_lock = portage_locks.lockdir(
+					self.settings["PORTAGE_BUILDDIR"])
+				try:
+					portage_locks.unlockdir(catdir_lock)
+				finally:
+					catdir_lock = None
+				# Eventually, we'd like to pass in the saved ebuild env here...
+				retval = doebuild(myebuildpath, "prerm", self.myroot,
+					self.settings, cleanup=cleanup, use_cache=0,
+					mydbapi=self.vartree.dbapi, tree="vartree",
+					vartree=self.vartree)
+				# XXX: Decide how to handle failures here.
+				if retval != os.EX_OK:
+					writemsg("!!! FAILED prerm: %s\n" % retval, noiselevel=-1)
+					return retval
+
+			self._unmerge_pkgfiles(pkgfiles)
+
+			if myebuildpath:
+				retval = doebuild(myebuildpath, "postrm", self.myroot,
+					 self.settings, use_cache=0, tree="vartree",
+					 mydbapi=self.vartree.dbapi, vartree=self.vartree)
+
+				# process logs created during pre/postrm
+				elog_process(self.mycpv, self.settings)
+
+				# XXX: Decide how to handle failures here.
+				if retval != os.EX_OK:
+					writemsg("!!! FAILED postrm: %s\n" % retval, noiselevel=-1)
+					return retval
+				doebuild(myebuildpath, "cleanrm", self.myroot, self.settings,
+					tree="vartree", mydbapi=self.vartree.dbapi,
+					vartree=self.vartree)
+
+		finally:
+			if builddir_lock:
+				portage_locks.unlockdir(builddir_lock)
+			try:
+				if myebuildpath and not catdir_lock:
+					# Lock catdir for removal if empty.
+					catdir_lock = portage_locks.lockdir(catdir)
+			finally:
+				if catdir_lock:
+					try:
+						os.rmdir(catdir)
+					except OSError, e:
+						if e.errno not in (errno.ENOENT,
+							errno.ENOTEMPTY, errno.EEXIST):
+							raise
+						del e
+					portage_locks.unlockdir(catdir_lock)
+		env_update(target_root=self.myroot, prev_mtimes=ldpath_mtimes,
+			contents=contents)
+		return os.EX_OK
+
+	def _unmerge_pkgfiles(self, pkgfiles):
+		"""
+		
+		Unmerges the contents of a package from the liveFS
+		Removes the VDB entry for self
+		
+		@param pkgfiles: typically self.getcontents()
+		@type pkgfiles: Dictionary { filename: [ 'type', '?', 'md5sum' ] }
+		@rtype: None
+		"""
+		global dircache
+		dircache={}
+
+		if not pkgfiles:
+			writemsg_stdout("No package files given... Grabbing a set.\n")
+			pkgfiles=self.getcontents()
+
+		if pkgfiles:
+			mykeys=pkgfiles.keys()
+			mykeys.sort()
+			mykeys.reverse()
+
+			#process symlinks second-to-last, directories last.
+			mydirs=[]
+			modprotect="/lib/modules/"
+			for objkey in mykeys:
+				obj = normalize_path(objkey)
+				if obj[:2]=="//":
+					obj=obj[1:]
+				statobj = None
+				try:
+					statobj = os.stat(obj)
+				except OSError:
+					pass
+				lstatobj = None
+				try:
+					lstatobj = os.lstat(obj)
+				except (OSError, AttributeError):
+					pass
+				islink = lstatobj is not None and stat.S_ISLNK(lstatobj.st_mode)
+				if statobj is None:
+					if not islink:
+						#we skip this if we're dealing with a symlink
+						#because os.stat() will operate on the
+						#link target rather than the link itself.
+						writemsg_stdout("--- !found "+str(pkgfiles[objkey][0])+ " %s\n" % obj)
+						continue
+				# next line includes a tweak to protect modules from being unmerged,
+				# but we don't protect modules from being overwritten if they are
+				# upgraded. We effectively only want one half of the config protection
+				# functionality for /lib/modules. For portage-ng both capabilities
+				# should be able to be independently specified.
+				if obj.startswith(modprotect):
+					writemsg_stdout("--- cfgpro %s %s\n" % (pkgfiles[objkey][0], obj))
+					continue
+
+				lmtime=str(lstatobj[stat.ST_MTIME])
+				if (pkgfiles[objkey][0] not in ("dir","fif","dev")) and (lmtime != pkgfiles[objkey][1]):
+					writemsg_stdout("--- !mtime %s %s\n" % (pkgfiles[objkey][0], obj))
+					continue
+
+				if pkgfiles[objkey][0]=="dir":
+					if statobj is None or not stat.S_ISDIR(statobj.st_mode):
+						writemsg_stdout("--- !dir   %s %s\n" % ("dir", obj))
+						continue
+					mydirs.append(obj)
+				elif pkgfiles[objkey][0]=="sym":
+					if not islink:
+						writemsg_stdout("--- !sym   %s %s\n" % ("sym", obj))
+						continue
+					try:
+						os.unlink(obj)
+						writemsg_stdout("<<<        %s %s\n" % ("sym",obj))
+					except (OSError,IOError),e:
+						writemsg_stdout("!!!        %s %s\n" % ("sym",obj))
+				elif pkgfiles[objkey][0]=="obj":
+					if statobj is None or not stat.S_ISREG(statobj.st_mode):
+						writemsg_stdout("--- !obj   %s %s\n" % ("obj", obj))
+						continue
+					mymd5 = None
+					try:
+						mymd5 = portage_checksum.perform_md5(obj, calc_prelink=1)
+					except portage_exception.FileNotFound, e:
+						# the file has disappeared between now and our stat call
+						writemsg_stdout("--- !obj   %s %s\n" % ("obj", obj))
+						continue
+
+					# string.lower is needed because db entries used to be in upper-case.  The
+					# string.lower allows for backwards compatibility.
+					if mymd5 != pkgfiles[objkey][2].lower():
+						writemsg_stdout("--- !md5   %s %s\n" % ("obj", obj))
+						continue
+					try:
+						os.unlink(obj)
+					except (OSError,IOError),e:
+						pass
+					writemsg_stdout("<<<        %s %s\n" % ("obj",obj))
+				elif pkgfiles[objkey][0]=="fif":
+					if not stat.S_ISFIFO(lstatobj[stat.ST_MODE]):
+						writemsg_stdout("--- !fif   %s %s\n" % ("fif", obj))
+						continue
+					writemsg_stdout("---        %s %s\n" % ("fif",obj))
+				elif pkgfiles[objkey][0]=="dev":
+					writemsg_stdout("---        %s %s\n" % ("dev",obj))
+
+			mydirs.sort()
+			mydirs.reverse()
+
+			for obj in mydirs:
+				try:
+					os.rmdir(obj)
+					writemsg_stdout("<<<        %s %s\n" % ("dir",obj))
+				except (OSError, IOError):
+					writemsg_stdout("--- !empty dir %s\n" % obj)
+
+		#remove self from vartree database so that our own virtual gets zapped if we're the last node
+		self.vartree.zap(self.mycpv)
+
+	def isowner(self,filename,destroot):
+		""" 
+		Check if filename is a new file or belongs to this package
+		(for this or a previous version)
+		
+		@param filename:
+		@type filename:
+		@param destroot:
+		@type destroot:
+		@rtype: Boolean
+		@returns:
+		1. True if this package owns the file.
+		2. False if this package does not own the file.
+		"""
+		destfile = normalize_path(
+			os.path.join(destroot, filename.lstrip(os.path.sep)))
+		try:
+			mylstat = os.lstat(destfile)
+		except (OSError, IOError):
+			return True
+
+		pkgfiles = self.getcontents()
+		if pkgfiles and filename in pkgfiles:
+			return True
+		if pkgfiles:
+			if self._contents_inodes is None:
+				self._contents_inodes = set()
+				for x in pkgfiles:
+					try:
+						lstat = os.lstat(x)
+						self._contents_inodes.add((lstat.st_dev, lstat.st_ino))
+					except OSError:
+						pass
+			if (mylstat.st_dev, mylstat.st_ino) in self._contents_inodes:
+				 return True
+
+		return False
+
+	def isprotected(self, filename):
+		"""In cases where an installed package in the same slot owns a
+		protected file that will be merged, bump the mtime on the installed
+		file in order to ensure that it isn't unmerged."""
+		if not self._config_protect.isprotected(filename):
+			return False
+		if self._installed_instance is None:
+			return True
+		mydata = self._installed_instance.getcontents().get(filename, None)
+		if mydata is None:
+			return True
+
+		# Bump the mtime in order to ensure that the old config file doesn't
+		# get unmerged.  The user will have an opportunity to merge the new
+		# config with the old one.
+		try:
+			os.utime(filename, None)
+		except OSError, e:
+			if e.errno != errno.ENOENT:
+				raise
+			del e
+			# The file has disappeared, so it's not protected.
+			return False
+		return True
+
+	def treewalk(self, srcroot, destroot, inforoot, myebuild, cleanup=0,
+		mydbapi=None, prev_mtimes=None):
+		"""
+		
+		This function does the following:
+		
+		Collision Protection.
+		calls doebuild(mydo=pkg_preinst)
+		Merges the package to the livefs
+		unmerges old version (if required)
+		calls doebuild(mydo=pkg_postinst)
+		calls env_update
+		
+		@param srcroot: Typically this is ${D}
+		@type srcroot: String (Path)
+		@param destroot: Path to merge to (usually ${ROOT})
+		@type destroot: String (Path)
+		@param inforoot: root of the vardb entry ?
+		@type inforoot: String (Path)
+		@param myebuild: path to the ebuild that we are processing
+		@type myebuild: String (Path)
+		@param mydbapi: dbapi which is handed to doebuild.
+		@type mydbapi: portdbapi instance
+		@param prev_mtimes: { Filename:mtime } mapping for env_update
+		@type prev_mtimes: Dictionary
+		@rtype: Boolean
+		@returns:
+		1. 0 on success
+		2. 1 on failure
+		
+		secondhand is a list of symlinks that have been skipped due to their target
+		not existing; we will merge these symlinks at a later time.
+		"""
+		if not os.path.isdir(srcroot):
+			writemsg("!!! Directory Not Found: D='%s'\n" % srcroot,
+			noiselevel=-1)
+			return 1
+
+		if not os.path.exists(self.dbcatdir):
+			os.makedirs(self.dbcatdir)
+
+		otherversions=[]
+		for v in self.vartree.dbapi.cp_list(self.mysplit[0]):
+			otherversions.append(v.split("/")[1])
+
+		slot_matches = self.vartree.dbapi.match(
+			"%s:%s" % (self.mysplit[0], self.settings["SLOT"]))
+		if slot_matches:
+			# Used by self.isprotected().
+			self._installed_instance = dblink(self.cat,
+				catsplit(slot_matches[0])[1], destroot, self.settings,
+				vartree=self.vartree)
+
+		# check for package collisions
+		if "collision-protect" in self.settings.features:
+			collision_ignore = set([normalize_path(myignore) for myignore in \
+				self.settings.get("COLLISION_IGNORE", "").split()])
+			myfilelist = listdir(srcroot, recursive=1, filesonly=1, followSymlinks=False)
+
+			# the linkcheck only works if we are in srcroot
+			mycwd = getcwd()
+			os.chdir(srcroot)
+			mysymlinks = filter(os.path.islink, listdir(srcroot, recursive=1, filesonly=0, followSymlinks=False))
+			myfilelist.extend(mysymlinks)
+			mysymlinked_directories = [s + os.path.sep for s in mysymlinks]
+			del mysymlinks
+
+
+			stopmerge=False
+			starttime=time.time()
+			i=0
+
+			otherpkg=[]
+			mypkglist=[]
+
+			if self.pkg in otherversions:
+				otherversions.remove(self.pkg)	# we already checked this package
+
+			myslot = self.settings["SLOT"]
+			for v in otherversions:
+				# only allow versions with same slot to overwrite files
+				if myslot == self.vartree.dbapi.aux_get("/".join((self.cat, v)), ["SLOT"])[0]:
+					mypkglist.append(
+						dblink(self.cat, v, destroot, self.settings,
+							vartree=self.vartree))
+
+			collisions = []
+
+			print green("*")+" checking "+str(len(myfilelist))+" files for package collisions"
+			for f in myfilelist:
+				nocheck = False
+				# listdir isn't intelligent enough to exclude symlinked dirs,
+				# so we have to do it ourself
+				for s in mysymlinked_directories:
+					if f.startswith(s):
+						nocheck = True
+						break
+				if nocheck:
+					continue
+				i=i+1
+				if i % 1000 == 0:
+					print str(i)+" files checked ..."
+				if f[0] != "/":
+					f="/"+f
+				isowned = False
+				for ver in [self]+mypkglist:
+					if (ver.isowner(f, destroot) or ver.isprotected(f)):
+						isowned = True
+						break
+				if not isowned:
+					collisions.append(f)
+					print "existing file "+f+" is not owned by this package"
+					stopmerge=True
+					if collision_ignore:
+						if f in collision_ignore:
+							stopmerge = False
+						else:
+							for myignore in collision_ignore:
+								if f.startswith(myignore + os.path.sep):
+									stopmerge = False
+									break
+			#print green("*")+" spent "+str(time.time()-starttime)+" seconds checking for file collisions"
+			if stopmerge:
+				print red("*")+" This package is blocked because it wants to overwrite"
+				print red("*")+" files belonging to other packages (see messages above)."
+				print red("*")+" If you have no clue what this is all about report it "
+				print red("*")+" as a bug for this package on http://bugs.gentoo.org"
+				print
+				print red("package "+self.cat+"/"+self.pkg+" NOT merged")
+				print
+				print
+				print "Searching all installed packages for file collisions..."
+				print "Press Ctrl-C to Stop"
+				print
+				""" Note: The isowner calls result in a stat call for *every*
+				single installed file, since the inode numbers are used to work
+				around the problem of ambiguous paths caused by symlinked files
+				and/or directories.  Though it is slow, it is as accurate as
+				possible."""
+				found_owner = False
+				for cpv in self.vartree.dbapi.cpv_all():
+					cat, pkg = catsplit(cpv)
+					mylink = dblink(cat, pkg, destroot, self.settings,
+						vartree=self.vartree)
+					mycollisions = []
+					for f in collisions:
+						if mylink.isowner(f, destroot):
+							mycollisions.append(f)
+					if mycollisions:
+						found_owner = True
+						print " * %s:" % cpv
+						print
+						for f in mycollisions:
+							print "     '%s'" % \
+								os.path.join(destroot, f.lstrip(os.path.sep))
+						print
+				if not found_owner:
+					print "None of the installed packages claim the above file(s)."
+					print
+				sys.exit(1)
+			try:
+				os.chdir(mycwd)
+			except OSError:
+				pass
+
+		if os.stat(srcroot).st_dev == os.stat(destroot).st_dev:
+			""" The merge process may move files out of the image directory,
+			which causes invalidation of the .installed flag."""
+			try:
+				os.unlink(os.path.join(
+					os.path.dirname(normalize_path(srcroot)), ".installed"))
+			except OSError, e:
+				if e.errno != errno.ENOENT:
+					raise
+				del e
+
+		# get old contents info for later unmerging
+		oldcontents = self.getcontents()
+
+		self.dbdir = self.dbtmpdir
+		self.delete()
+		if not os.path.exists(self.dbtmpdir):
+			os.makedirs(self.dbtmpdir)
+
+		writemsg_stdout(">>> Merging %s %s %s\n" % (self.mycpv,"to",destroot))
+
+		# run preinst script
+		if myebuild is None:
+			myebuild = os.path.join(inforoot, self.pkg + ".ebuild")
+		a = doebuild(myebuild, "preinst", destroot, self.settings, cleanup=cleanup,
+			use_cache=0, tree=self.treetype, mydbapi=mydbapi,
+			vartree=self.vartree)
+
+		# XXX: Decide how to handle failures here.
+		if a != os.EX_OK:
+			writemsg("!!! FAILED preinst: "+str(a)+"\n", noiselevel=-1)
+			return a
+
+		# copy "info" files (like SLOT, CFLAGS, etc.) into the database
+		for x in listdir(inforoot):
+			self.copyfile(inforoot+"/"+x)
+
+		# get current counter value (counter_tick also takes care of incrementing it)
+		# XXX Need to make this destroot, but it needs to be initialized first. XXX
+		# XXX bis: leads to some invalidentry() call through cp_all().
+		counter = self.vartree.dbapi.counter_tick(self.myroot, mycpv=self.mycpv)
+		# write local package counter for recording
+		lcfile = open(self.dbtmpdir+"/COUNTER","w")
+		lcfile.write(str(counter))
+		lcfile.close()
+
+		# open CONTENTS file (possibly overwriting old one) for recording
+		outfile=open(self.dbtmpdir+"/CONTENTS","w")
+
+		self.updateprotect()
+
+		#if we have a file containing previously-merged config file md5sums, grab it.
+		conf_mem_file = os.path.join(destroot, CONFIG_MEMORY_FILE)
+		cfgfiledict = grabdict(conf_mem_file)
+		if self.settings.has_key("NOCONFMEM"):
+			cfgfiledict["IGNORE"]=1
+		else:
+			cfgfiledict["IGNORE"]=0
+
+		# Timestamp for files being merged.  Use time() - 1 in order to prevent
+		# a collision with timestamps that are bumped by the utime() call
+		# inside isprotected().  This ensures that the new and old config have
+		# different timestamps (for the benefit of programs like rsync that
+		# that need distiguishable timestamps to detect file changes).
+		mymtime = long(time.time() - 1)
+
+		# set umask to 0 for merging; back up umask, save old one in prevmask (since this is a global change)
+		prevmask   = os.umask(0)
+		secondhand = []
+
+		# we do a first merge; this will recurse through all files in our srcroot but also build up a
+		# "second hand" of symlinks to merge later
+		if self.mergeme(srcroot,destroot,outfile,secondhand,"",cfgfiledict,mymtime):
+			return 1
+
+		# now, it's time for dealing our second hand; we'll loop until we can't merge anymore.	The rest are
+		# broken symlinks.  We'll merge them too.
+		lastlen=0
+		while len(secondhand) and len(secondhand)!=lastlen:
+			# clear the thirdhand.	Anything from our second hand that
+			# couldn't get merged will be added to thirdhand.
+
+			thirdhand=[]
+			self.mergeme(srcroot,destroot,outfile,thirdhand,secondhand,cfgfiledict,mymtime)
+
+			#swap hands
+			lastlen=len(secondhand)
+
+			# our thirdhand now becomes our secondhand.  It's ok to throw
+			# away secondhand since thirdhand contains all the stuff that
+			# couldn't be merged.
+			secondhand = thirdhand
+
+		if len(secondhand):
+			# force merge of remaining symlinks (broken or circular; oh well)
+			self.mergeme(srcroot,destroot,outfile,None,secondhand,cfgfiledict,mymtime)
+
+		#restore umask
+		os.umask(prevmask)
+
+		#if we opened it, close it
+		outfile.flush()
+		outfile.close()
+
+		if os.path.exists(self.dbpkgdir):
+			writemsg_stdout(">>> Safely unmerging already-installed instance...\n")
+			self.dbdir = self.dbpkgdir
+			self.unmerge(oldcontents, trimworld=0, ldpath_mtimes=prev_mtimes)
+			self.dbdir = self.dbtmpdir
+			writemsg_stdout(">>> Original instance of package unmerged safely.\n")
+
+		# We hold both directory locks.
+		self.dbdir = self.dbpkgdir
+		self.delete()
+		movefile(self.dbtmpdir, self.dbpkgdir, mysettings=self.settings)
+		contents = self.getcontents()
+
+		#write out our collection of md5sums
+		if cfgfiledict.has_key("IGNORE"):
+			del cfgfiledict["IGNORE"]
+
+		my_private_path = os.path.join(destroot, PRIVATE_PATH)
+		if not os.path.exists(my_private_path):
+			os.makedirs(my_private_path)
+			os.chown(my_private_path, os.getuid(), portage_gid)
+			os.chmod(my_private_path, 02770)
+
+		writedict(cfgfiledict, conf_mem_file)
+		del conf_mem_file
+
+		#do postinst script
+		a = doebuild(myebuild, "postinst", destroot, self.settings, use_cache=0,
+			tree=self.treetype, mydbapi=mydbapi, vartree=self.vartree)
+
+		# XXX: Decide how to handle failures here.
+		if a != os.EX_OK:
+			writemsg("!!! FAILED postinst: "+str(a)+"\n", noiselevel=-1)
+			return a
+
+		downgrade = False
+		for v in otherversions:
+			if pkgcmp(catpkgsplit(self.pkg)[1:], catpkgsplit(v)[1:]) < 0:
+				downgrade = True
+
+		#update environment settings, library paths. DO NOT change symlinks.
+		env_update(makelinks=(not downgrade),
+			target_root=self.settings["ROOT"], prev_mtimes=prev_mtimes,
+			contents=contents)
+		#dircache may break autoclean because it remembers the -MERGING-pkg file
+		global dircache
+		if dircache.has_key(self.dbcatdir):
+			del dircache[self.dbcatdir]
+		writemsg_stdout(">>> %s %s\n" % (self.mycpv,"merged."))
+
+		# Process ebuild logfiles
+		elog_process(self.mycpv, self.settings)
+		if "noclean" not in self.settings.features:
+			doebuild(myebuild, "clean", destroot, self.settings,
+				tree=self.treetype, mydbapi=mydbapi, vartree=self.vartree)
+		return os.EX_OK
+
+	def mergeme(self,srcroot,destroot,outfile,secondhand,stufftomerge,cfgfiledict,thismtime):
+		"""
+		
+		This function handles actual merging of the package contents to the livefs.
+		It also handles config protection.
+		
+		@param srcroot: Where are we copying files from (usually ${D})
+		@type srcroot: String (Path)
+		@param destroot: Typically ${ROOT}
+		@type destroot: String (Path)
+		@param outfile: File to log operations to
+		@type outfile: File Object
+		@param secondhand: A set of items to merge in pass two (usually
+		or symlinks that point to non-existing files that may get merged later)
+		@type secondhand: List
+		@param stufftomerge: Either a diretory to merge, or a list of items.
+		@type stufftomerge: String or List
+		@param cfgfiledict: { File:mtime } mapping for config_protected files
+		@type cfgfiledict: Dictionary
+		@param thismtime: The current time (typically long(time.time())
+		@type thismtime: Long
+		@rtype: None or Boolean
+		@returns:
+		1. True on failure
+		2. None otherwise
+		
+		"""
+		from os.path import sep, join
+		srcroot = normalize_path(srcroot).rstrip(sep) + sep
+		destroot = normalize_path(destroot).rstrip(sep) + sep
+		# this is supposed to merge a list of files.  There will be 2 forms of argument passing.
+		if type(stufftomerge)==types.StringType:
+			#A directory is specified.  Figure out protection paths, listdir() it and process it.
+			mergelist = listdir(join(srcroot, stufftomerge))
+			offset=stufftomerge
+		else:
+			mergelist=stufftomerge
+			offset=""
+		for x in mergelist:
+			mysrc = join(srcroot, offset, x)
+			mydest = join(destroot, offset, x)
+			# myrealdest is mydest without the $ROOT prefix (makes a difference if ROOT!="/")
+			myrealdest = join(sep, offset, x)
+			# stat file once, test using S_* macros many times (faster that way)
+			try:
+				mystat=os.lstat(mysrc)
+			except OSError, e:
+				writemsg("\n")
+				writemsg(red("!!! ERROR: There appears to be ")+bold("FILE SYSTEM CORRUPTION.")+red(" A file that is listed\n"))
+				writemsg(red("!!!        as existing is not capable of being stat'd. If you are using an\n"))
+				writemsg(red("!!!        experimental kernel, please boot into a stable one, force an fsck,\n"))
+				writemsg(red("!!!        and ensure your filesystem is in a sane state. ")+bold("'shutdown -Fr now'\n"))
+				writemsg(red("!!!        File:  ")+str(mysrc)+"\n", noiselevel=-1)
+				writemsg(red("!!!        Error: ")+str(e)+"\n", noiselevel=-1)
+				sys.exit(1)
+			except Exception, e:
+				writemsg("\n")
+				writemsg(red("!!! ERROR: An unknown error has occurred during the merge process.\n"))
+				writemsg(red("!!!        A stat call returned the following error for the following file:"))
+				writemsg(    "!!!        Please ensure that your filesystem is intact, otherwise report\n")
+				writemsg(    "!!!        this as a portage bug at bugs.gentoo.org. Append 'emerge info'.\n")
+				writemsg(    "!!!        File:  "+str(mysrc)+"\n", noiselevel=-1)
+				writemsg(    "!!!        Error: "+str(e)+"\n", noiselevel=-1)
+				sys.exit(1)
+
+
+			mymode=mystat[stat.ST_MODE]
+			# handy variables; mydest is the target object on the live filesystems;
+			# mysrc is the source object in the temporary install dir
+			try:
+				mydmode = os.lstat(mydest).st_mode
+			except OSError, e:
+				if e.errno != errno.ENOENT:
+					raise
+				del e
+				#dest file doesn't exist
+				mydmode=None
+
+			if stat.S_ISLNK(mymode):
+				# we are merging a symbolic link
+				myabsto=abssymlink(mysrc)
+				if myabsto.startswith(srcroot):
+					myabsto=myabsto[len(srcroot):]
+				myabsto = myabsto.lstrip(sep)
+				myto=os.readlink(mysrc)
+				if self.settings and self.settings["D"]:
+					if myto.startswith(self.settings["D"]):
+						myto=myto[len(self.settings["D"]):]
+				# myrealto contains the path of the real file to which this symlink points.
+				# we can simply test for existence of this file to see if the target has been merged yet
+				myrealto = normalize_path(os.path.join(destroot, myabsto))
+				if mydmode!=None:
+					#destination exists
+					if not stat.S_ISLNK(mydmode):
+						if stat.S_ISDIR(mydmode):
+							# directory in the way: we can't merge a symlink over a directory
+							# we won't merge this, continue with next file...
+							continue
+
+						if os.path.exists(mysrc) and stat.S_ISDIR(os.stat(mysrc)[stat.ST_MODE]):
+							# Kill file blocking installation of symlink to dir #71787
+							pass
+						elif self.isprotected(mydest):
+							# Use md5 of the target in ${D} if it exists...
+							try:
+								newmd5 = portage_checksum.perform_md5(
+									join(srcroot, myabsto))
+							except portage_exception.FileNotFound:
+								# Maybe the target is merged already.
+								try:
+									newmd5 = portage_checksum.perform_md5(
+										myrealto)
+								except portage_exception.FileNotFound:
+									newmd5 = None
+							mydest = new_protect_filename(mydest,newmd5=newmd5)
+
+				# if secondhand is None it means we're operating in "force" mode and should not create a second hand.
+				if (secondhand!=None) and (not os.path.exists(myrealto)):
+					# either the target directory doesn't exist yet or the target file doesn't exist -- or
+					# the target is a broken symlink.  We will add this file to our "second hand" and merge
+					# it later.
+					secondhand.append(mysrc[len(srcroot):])
+					continue
+				# unlinking no longer necessary; "movefile" will overwrite symlinks atomically and correctly
+				mymtime=movefile(mysrc,mydest,newmtime=thismtime,sstat=mystat, mysettings=self.settings)
+				if mymtime!=None:
+					writemsg_stdout(">>> %s -> %s\n" % (mydest, myto))
+					outfile.write("sym "+myrealdest+" -> "+myto+" "+str(mymtime)+"\n")
+				else:
+					print "!!! Failed to move file."
+					print "!!!",mydest,"->",myto
+					sys.exit(1)
+			elif stat.S_ISDIR(mymode):
+				# we are merging a directory
+				if mydmode!=None:
+					# destination exists
+
+					if bsd_chflags:
+						# Save then clear flags on dest.
+						dflags=bsd_chflags.lgetflags(mydest)
+						if dflags != 0 and bsd_chflags.lchflags(mydest, 0) < 0:
+							writemsg("!!! Couldn't clear flags on '"+mydest+"'.\n",
+								noiselevel=-1)
+
+					if not os.access(mydest, os.W_OK):
+						pkgstuff = pkgsplit(self.pkg)
+						writemsg("\n!!! Cannot write to '"+mydest+"'.\n", noiselevel=-1)
+						writemsg("!!! Please check permissions and directories for broken symlinks.\n")
+						writemsg("!!! You may start the merge process again by using ebuild:\n")
+						writemsg("!!! ebuild "+self.settings["PORTDIR"]+"/"+self.cat+"/"+pkgstuff[0]+"/"+self.pkg+".ebuild merge\n")
+						writemsg("!!! And finish by running this: env-update\n\n")
+						return 1
+
+					if stat.S_ISLNK(mydmode) or stat.S_ISDIR(mydmode):
+						# a symlink to an existing directory will work for us; keep it:
+						writemsg_stdout("--- %s/\n" % mydest)
+						if bsd_chflags:
+							bsd_chflags.lchflags(mydest, dflags)
+					else:
+						# a non-directory and non-symlink-to-directory.  Won't work for us.  Move out of the way.
+						if movefile(mydest,mydest+".backup", mysettings=self.settings) is None:
+							sys.exit(1)
+						print "bak",mydest,mydest+".backup"
+						#now create our directory
+						if self.settings.selinux_enabled():
+							sid = selinux.get_sid(mysrc)
+							selinux.secure_mkdir(mydest,sid)
+						else:
+							os.mkdir(mydest)
+						if bsd_chflags:
+							bsd_chflags.lchflags(mydest, dflags)
+						os.chmod(mydest,mystat[0])
+						os.chown(mydest,mystat[4],mystat[5])
+						writemsg_stdout(">>> %s/\n" % mydest)
+				else:
+					#destination doesn't exist
+					if self.settings.selinux_enabled():
+						sid = selinux.get_sid(mysrc)
+						selinux.secure_mkdir(mydest,sid)
+					else:
+						os.mkdir(mydest)
+					os.chmod(mydest,mystat[0])
+					os.chown(mydest,mystat[4],mystat[5])
+					writemsg_stdout(">>> %s/\n" % mydest)
+				outfile.write("dir "+myrealdest+"\n")
+				# recurse and merge this directory
+				if self.mergeme(srcroot, destroot, outfile, secondhand,
+					join(offset, x), cfgfiledict, thismtime):
+					return 1
+			elif stat.S_ISREG(mymode):
+				# we are merging a regular file
+				mymd5=portage_checksum.perform_md5(mysrc,calc_prelink=1)
+				# calculate config file protection stuff
+				mydestdir=os.path.dirname(mydest)
+				moveme=1
+				zing="!!!"
+				if mydmode!=None:
+					# destination file exists
+					if stat.S_ISDIR(mydmode):
+						# install of destination is blocked by an existing directory with the same name
+						moveme=0
+						writemsg_stdout("!!! %s\n" % mydest)
+					elif stat.S_ISREG(mydmode) or (stat.S_ISLNK(mydmode) and os.path.exists(mydest) and stat.S_ISREG(os.stat(mydest)[stat.ST_MODE])):
+						cfgprot=0
+						# install of destination is blocked by an existing regular file,
+						# or by a symlink to an existing regular file;
+						# now, config file management may come into play.
+						# we only need to tweak mydest if cfg file management is in play.
+						if self.isprotected(mydest):
+							# we have a protection path; enable config file management.
+							destmd5=portage_checksum.perform_md5(mydest,calc_prelink=1)
+							if mymd5==destmd5:
+								#file already in place; simply update mtimes of destination
+								os.utime(mydest,(thismtime,thismtime))
+								zing="---"
+								moveme=0
+							else:
+								if mymd5 == cfgfiledict.get(myrealdest, [None])[0]:
+									""" An identical update has previously been
+									merged.  Skip it unless the user has chosen
+									--noconfmem."""
+									zing = "-o-"
+									moveme = cfgfiledict["IGNORE"]
+									cfgprot = cfgfiledict["IGNORE"]
+								else:
+									moveme = 1
+									cfgprot = 1
+							if moveme:
+								# Merging a new file, so update confmem.
+								cfgfiledict[myrealdest] = [mymd5]
+							elif destmd5 == cfgfiledict.get(myrealdest, [None])[0]:
+								"""A previously remembered update has been
+								accepted, so it is removed from confmem."""
+								del cfgfiledict[myrealdest]
+						if cfgprot:
+							mydest = new_protect_filename(mydest, newmd5=mymd5)
+
+				# whether config protection or not, we merge the new file the
+				# same way.  Unless moveme=0 (blocking directory)
+				if moveme:
+					mymtime=movefile(mysrc,mydest,newmtime=thismtime,sstat=mystat, mysettings=self.settings)
+					if mymtime is None:
+						sys.exit(1)
+					zing=">>>"
+				else:
+					mymtime = long(time.time())
+					# We need to touch the destination so that on --update the
+					# old package won't yank the file with it. (non-cfgprot related)
+					os.utime(mydest, (mymtime, mymtime))
+					zing="---"
+				if self.settings["USERLAND"] == "Darwin" and myrealdest[-2:] == ".a":
+
+					# XXX kludge, can be killed when portage stops relying on
+					# md5+mtime, and uses refcounts
+					# alright, we've fooled w/ mtime on the file; this pisses off static archives
+					# basically internal mtime != file's mtime, so the linker (falsely) thinks
+					# the archive is stale, and needs to have it's toc rebuilt.
+
+					myf = open(mydest, "r+")
+
+					# ar mtime field is digits padded with spaces, 12 bytes.
+					lms=str(thismtime+5).ljust(12)
+					myf.seek(0)
+					magic=myf.read(8)
+					if magic != "!<arch>\n":
+						# not an archive (dolib.a from portage.py makes it here fex)
+						myf.close()
+					else:
+						st = os.stat(mydest)
+						while myf.tell() < st.st_size - 12:
+							# skip object name
+							myf.seek(16,1)
+
+							# update mtime
+							myf.write(lms)
+
+							# skip uid/gid/mperm
+							myf.seek(20,1)
+
+							# read the archive member's size
+							x=long(myf.read(10))
+
+							# skip the trailing newlines, and add the potential
+							# extra padding byte if it's not an even size
+							myf.seek(x + 2 + (x % 2),1)
+
+						# and now we're at the end. yay.
+						myf.close()
+						mymd5 = portage_checksum.perform_md5(mydest, calc_prelink=1)
+					os.utime(mydest,(thismtime,thismtime))
+
+				if mymtime!=None:
+					zing=">>>"
+					outfile.write("obj "+myrealdest+" "+mymd5+" "+str(mymtime)+"\n")
+				writemsg_stdout("%s %s\n" % (zing,mydest))
+			else:
+				# we are merging a fifo or device node
+				zing="!!!"
+				if mydmode is None:
+					# destination doesn't exist
+					if movefile(mysrc,mydest,newmtime=thismtime,sstat=mystat, mysettings=self.settings)!=None:
+						zing=">>>"
+					else:
+						sys.exit(1)
+				if stat.S_ISFIFO(mymode):
+					outfile.write("fif %s\n" % myrealdest)
+				else:
+					outfile.write("dev %s\n" % myrealdest)
+				writemsg_stdout(zing+" "+mydest+"\n")
+
+	def merge(self, mergeroot, inforoot, myroot, myebuild=None, cleanup=0,
+		mydbapi=None, prev_mtimes=None):
+		try:
+			self.lockdb()
+			return self.treewalk(mergeroot, myroot, inforoot, myebuild,
+				cleanup=cleanup, mydbapi=mydbapi, prev_mtimes=prev_mtimes)
+		finally:
+			self.unlockdb()
+
+	def getstring(self,name):
+		"returns contents of a file with whitespace converted to spaces"
+		if not os.path.exists(self.dbdir+"/"+name):
+			return ""
+		myfile=open(self.dbdir+"/"+name,"r")
+		mydata=myfile.read().split()
+		myfile.close()
+		return " ".join(mydata)
+
+	def copyfile(self,fname):
+		shutil.copyfile(fname,self.dbdir+"/"+os.path.basename(fname))
+
+	def getfile(self,fname):
+		if not os.path.exists(self.dbdir+"/"+fname):
+			return ""
+		myfile=open(self.dbdir+"/"+fname,"r")
+		mydata=myfile.read()
+		myfile.close()
+		return mydata
+
+	def setfile(self,fname,data):
+		write_atomic(os.path.join(self.dbdir, fname), data)
+
+	def getelements(self,ename):
+		if not os.path.exists(self.dbdir+"/"+ename):
+			return []
+		myelement=open(self.dbdir+"/"+ename,"r")
+		mylines=myelement.readlines()
+		myreturn=[]
+		for x in mylines:
+			for y in x[:-1].split():
+				myreturn.append(y)
+		myelement.close()
+		return myreturn
+
+	def setelements(self,mylist,ename):
+		myelement=open(self.dbdir+"/"+ename,"w")
+		for x in mylist:
+			myelement.write(x+"\n")
+		myelement.close()
+
+	def isregular(self):
+		"Is this a regular package (does it have a CATEGORY file?  A dblink can be virtual *and* regular)"
+		return os.path.exists(self.dbdir+"/CATEGORY")
+
+class FetchlistDict(UserDict.DictMixin):
+	"""This provide a mapping interface to retrieve fetch lists.  It's used
+	to allow portage_manifest.Manifest to access fetch lists via a standard
+	mapping interface rather than use the dbapi directly."""
+	def __init__(self, pkgdir, settings, mydbapi):
+		"""pkgdir is a directory containing ebuilds and settings is passed into
+		portdbapi.getfetchlist for __getitem__ calls."""
+		self.pkgdir = pkgdir
+		self.cp = os.sep.join(pkgdir.split(os.sep)[-2:])
+		self.settings = settings
+		self.mytree = os.path.realpath(os.path.dirname(os.path.dirname(pkgdir)))
+		self.portdb = mydbapi
+	def __getitem__(self, pkg_key):
+		"""Returns the complete fetch list for a given package."""
+		return self.portdb.getfetchlist(pkg_key, mysettings=self.settings,
+			all=True, mytree=self.mytree)[1]
+	def has_key(self, pkg_key):
+		"""Returns true if the given package exists within pkgdir."""
+		return pkg_key in self.keys()
+	def keys(self):
+		"""Returns keys for all packages within pkgdir"""
+		return self.portdb.cp_list(self.cp, mytree=self.mytree)
+
+def pkgmerge(mytbz2, myroot, mysettings, mydbapi=None, vartree=None, prev_mtimes=None):
+	"""will merge a .tbz2 file, returning a list of runtime dependencies
+		that must be satisfied, or None if there was a merge error.	This
+		code assumes the package exists."""
+	global db
+	if mydbapi is None:
+		mydbapi = db[myroot]["bintree"].dbapi
+	if vartree is None:
+		vartree = db[myroot]["vartree"]
+	if mytbz2[-5:]!=".tbz2":
+		print "!!! Not a .tbz2 file"
+		return 1
+
+	tbz2_lock = None
+	builddir_lock = None
+	catdir_lock = None
+	try:
+		""" Don't lock the tbz2 file because the filesytem could be readonly or
+		shared by a cluster."""
+		#tbz2_lock = portage_locks.lockfile(mytbz2, wantnewlockfile=1)
+
+		mypkg = os.path.basename(mytbz2)[:-5]
+		xptbz2 = xpak.tbz2(mytbz2)
+		mycat = xptbz2.getfile("CATEGORY")
+		if not mycat:
+			writemsg("!!! CATEGORY info missing from info chunk, aborting...\n",
+				noiselevel=-1)
+			return 1
+		mycat = mycat.strip()
+
+		# These are the same directories that would be used at build time.
+		builddir = os.path.join(
+			mysettings["PORTAGE_TMPDIR"], "portage", mycat, mypkg)
+		catdir = os.path.dirname(builddir)
+		pkgloc = os.path.join(builddir, "image")
+		infloc = os.path.join(builddir, "build-info")
+		myebuild = os.path.join(
+			infloc, os.path.basename(mytbz2)[:-4] + "ebuild")
+		portage_util.ensure_dirs(os.path.dirname(catdir),
+			uid=portage_uid, gid=portage_gid, mode=070, mask=0)
+		catdir_lock = portage_locks.lockdir(catdir)
+		portage_util.ensure_dirs(catdir,
+			uid=portage_uid, gid=portage_gid, mode=070, mask=0)
+		builddir_lock = portage_locks.lockdir(builddir)
+		try:
+			portage_locks.unlockdir(catdir_lock)
+		finally:
+			catdir_lock = None
+		try:
+			shutil.rmtree(builddir)
+		except (IOError, OSError), e:
+			if e.errno != errno.ENOENT:
+				raise
+			del e
+		for mydir in (builddir, pkgloc, infloc):
+			portage_util.ensure_dirs(mydir, uid=portage_uid,
+				gid=portage_gid, mode=0755)
+		writemsg_stdout(">>> Extracting info\n")
+		xptbz2.unpackinfo(infloc)
+		mysettings.load_infodir(infloc)
+		# Store the md5sum in the vdb.
+		fp = open(os.path.join(infloc, "BINPKGMD5"), "w")
+		fp.write(str(portage_checksum.perform_md5(mytbz2))+"\n")
+		fp.close()
+
+		debug = mysettings.get("PORTAGE_DEBUG", "") == "1"
+
+		# Eventually we'd like to pass in the saved ebuild env here.
+		retval = doebuild(myebuild, "setup", myroot, mysettings, debug=debug,
+			tree="bintree", mydbapi=mydbapi, vartree=vartree)
+		if retval != os.EX_OK:
+			writemsg("!!! Setup failed: %s\n" % retval, noiselevel=-1)
+			return retval
+
+		writemsg_stdout(">>> Extracting %s\n" % mypkg)
+		retval = portage_exec.spawn_bash(
+			"bzip2 -dqc -- '%s' | tar -xp -C '%s' -f -" % (mytbz2, pkgloc),
+			env=mysettings.environ())
+		if retval != os.EX_OK:
+			writemsg("!!! Error Extracting '%s'\n" % mytbz2, noiselevel=-1)
+			return retval
+		#portage_locks.unlockfile(tbz2_lock)
+		#tbz2_lock = None
+
+		mylink = dblink(mycat, mypkg, myroot, mysettings, vartree=vartree,
+			treetype="bintree")
+		retval = mylink.merge(pkgloc, infloc, myroot, myebuild, cleanup=0,
+			mydbapi=mydbapi, prev_mtimes=prev_mtimes)
+		return retval
+	finally:
+		if tbz2_lock:
+			portage_locks.unlockfile(tbz2_lock)
+		if builddir_lock:
+			try:
+				shutil.rmtree(builddir)
+			except (IOError, OSError), e:
+				if e.errno != errno.ENOENT:
+					raise
+				del e
+			portage_locks.unlockdir(builddir_lock)
+			try:
+				if not catdir_lock:
+					# Lock catdir for removal if empty.
+					catdir_lock = portage_locks.lockdir(catdir)
+			finally:
+				if catdir_lock:
+					try:
+						os.rmdir(catdir)
+					except OSError, e:
+						if e.errno not in (errno.ENOENT,
+							errno.ENOTEMPTY, errno.EEXIST):
+							raise
+						del e
+					portage_locks.unlockdir(catdir_lock)
+
+def deprecated_profile_check():
+	if not os.access(DEPRECATED_PROFILE_FILE, os.R_OK):
+		return False
+	deprecatedfile = open(DEPRECATED_PROFILE_FILE, "r")
+	dcontent = deprecatedfile.readlines()
+	deprecatedfile.close()
+	newprofile = dcontent[0]
+	writemsg(red("\n!!! Your current profile is deprecated and not supported anymore.\n"),
+		noiselevel=-1)
+	writemsg(red("!!! Please upgrade to the following profile if possible:\n"),
+		noiselevel=-1)
+	writemsg(8*" "+green(newprofile)+"\n", noiselevel=-1)
+	if len(dcontent) > 1:
+		writemsg("To upgrade do the following steps:\n", noiselevel=-1)
+		for myline in dcontent[1:]:
+			writemsg(myline, noiselevel=-1)
+		writemsg("\n\n", noiselevel=-1)
+	return True
+
+# gets virtual package settings
+def getvirtuals(myroot):
+	global settings
+	writemsg("--- DEPRECATED call to getvirtual\n")
+	return settings.getvirtuals(myroot)
+
+def commit_mtimedb(mydict=None, filename=None):
+	if mydict is None:
+		global mtimedb
+		if "mtimedb" not in globals() or mtimedb is None:
+			return
+		mtimedb.commit()
+		return
+	if filename is None:
+		global mtimedbfile
+		filename = mtimedbfile
+	mydict["version"] = VERSION
+	d = {} # for full backward compat, pickle it as a plain dict object.
+	d.update(mydict)
+	try:
+		f = atomic_ofstream(filename)
+		cPickle.dump(d, f, -1)
+		f.close()
+		portage_util.apply_secpass_permissions(filename, uid=uid, gid=portage_gid, mode=0664)
+	except (IOError, OSError), e:
+		pass
+
+def portageexit():
+	global uid,portage_gid,portdb,db
+	if secpass and not os.environ.has_key("SANDBOX_ACTIVE"):
+		close_portdbapi_caches()
+		commit_mtimedb()
+
+atexit_register(portageexit)
+
+def global_updates(mysettings, trees, prev_mtimes):
+	"""
+	Perform new global updates if they exist in $PORTDIR/profiles/updates/.
+
+	@param mysettings: A config instance for ROOT="/".
+	@type mysettings: config
+	@param trees: A dictionary containing portage trees.
+	@type trees: dict
+	@param prev_mtimes: A dictionary containing mtimes of files located in
+		$PORTDIR/profiles/updates/.
+	@type prev_mtimes: dict
+	@rtype: None or List
+	@return: None if no were no updates, otherwise a list of update commands
+		that have been performed.
+	"""
+	# only do this if we're root and not running repoman/ebuild digest
+	global secpass
+	if secpass < 2 or "SANDBOX_ACTIVE" in os.environ:
+		return
+	updpath = os.path.join(mysettings["PORTDIR"], "profiles", "updates")
+
+	try:
+		if mysettings["PORTAGE_CALLER"] == "fixpackages":
+			update_data = grab_updates(updpath)
+		else:
+			update_data = grab_updates(updpath, prev_mtimes)
+	except portage_exception.DirectoryNotFound:
+		writemsg("--- 'profiles/updates' is empty or not available. Empty portage tree?\n")
+		return
+	myupd = None
+	if len(update_data) > 0:
+		do_upgrade_packagesmessage = 0
+		myupd = []
+		timestamps = {}
+		for mykey, mystat, mycontent in update_data:
+			writemsg_stdout("\n\n")
+			writemsg_stdout(green("Performing Global Updates: ")+bold(mykey)+"\n")
+			writemsg_stdout("(Could take a couple of minutes if you have a lot of binary packages.)\n")
+			writemsg_stdout("  "+bold(".")+"='update pass'  "+bold("*")+"='binary update'  "+bold("@")+"='/var/db move'\n"+"  "+bold("s")+"='/var/db SLOT move' "+bold("S")+"='binary SLOT move' "+bold("p")+"='update /etc/portage/package.*'\n")
+			valid_updates, errors = parse_updates(mycontent)
+			myupd.extend(valid_updates)
+			writemsg_stdout(len(valid_updates) * "." + "\n")
+			if len(errors) == 0:
+				# Update our internal mtime since we
+				# processed all of our directives.
+				timestamps[mykey] = long(mystat.st_mtime)
+			else:
+				for msg in errors:
+					writemsg("%s\n" % msg, noiselevel=-1)
+
+		update_config_files("/",
+			mysettings.get("CONFIG_PROTECT","").split(),
+			mysettings.get("CONFIG_PROTECT_MASK","").split(),
+			myupd)
+
+		trees["/"]["bintree"] = binarytree("/", mysettings["PKGDIR"],
+			settings=mysettings)
+		for update_cmd in myupd:
+			if update_cmd[0] == "move":
+				trees["/"]["vartree"].dbapi.move_ent(update_cmd)
+				trees["/"]["bintree"].move_ent(update_cmd)
+			elif update_cmd[0] == "slotmove":
+				trees["/"]["vartree"].dbapi.move_slot_ent(update_cmd)
+				trees["/"]["bintree"].move_slot_ent(update_cmd)
+
+		# The above global updates proceed quickly, so they
+		# are considered a single mtimedb transaction.
+		if len(timestamps) > 0:
+			# We do not update the mtime in the mtimedb
+			# until after _all_ of the above updates have
+			# been processed because the mtimedb will
+			# automatically commit when killed by ctrl C.
+			for mykey, mtime in timestamps.iteritems():
+				prev_mtimes[mykey] = mtime
+
+		# We gotta do the brute force updates for these now.
+		if mysettings["PORTAGE_CALLER"] == "fixpackages" or \
+		"fixpackages" in mysettings.features:
+			trees["/"]["bintree"].update_ents(myupd)
+		else:
+			do_upgrade_packagesmessage = 1
+
+		# Update progress above is indicated by characters written to stdout so
+		# we print a couple new lines here to separate the progress output from
+		# what follows.
+		print
+		print
+
+		if do_upgrade_packagesmessage and \
+			listdir(os.path.join(mysettings["PKGDIR"], "All"), EmptyOnError=1):
+			writemsg_stdout(" ** Skipping packages. Run 'fixpackages' or set it in FEATURES to fix the")
+			writemsg_stdout("\n    tbz2's in the packages directory. "+bold("Note: This can take a very long time."))
+			writemsg_stdout("\n")
+	if myupd:
+		return myupd
+
+#continue setting up other trees
+
+class MtimeDB(dict):
+	def __init__(self, filename):
+		dict.__init__(self)
+		self.filename = filename
+		self._load(filename)
+
+	def _load(self, filename):
+		try:
+			f = open(filename)
+			mypickle = cPickle.Unpickler(f)
+			mypickle.find_global = None
+			d = mypickle.load()
+			f.close()
+			del f
+		except (IOError, OSError, EOFError, cPickle.UnpicklingError):
+			d = {}
+
+		if "old" in d:
+			d["updates"] = d["old"]
+			del d["old"]
+		if "cur" in d:
+			del d["cur"]
+
+		d.setdefault("starttime", 0)
+		d.setdefault("version", "")
+		for k in ("info", "ldpath", "updates"):
+			d.setdefault(k, {})
+
+		mtimedbkeys = set(("info", "ldpath", "resume", "resume_backup",
+			"starttime", "updates", "version"))
+
+		for k in d.keys():
+			if k not in mtimedbkeys:
+				writemsg("Deleting invalid mtimedb key: %s\n" % str(k))
+				del d[k]
+		self.update(d)
+		self._clean_data = copy.deepcopy(d)
+
+	def commit(self):
+		if not self.filename:
+			return
+		d = {}
+		d.update(self)
+		# Only commit if the internal state has changed.
+		if d != self._clean_data:
+			commit_mtimedb(mydict=d, filename=self.filename)
+			self._clean_data = copy.deepcopy(d)
+
+def create_trees(config_root=None, target_root=None, trees=None):
+	if trees is None:
+		trees = {}
+	else:
+		# clean up any existing portdbapi instances
+		for myroot in trees:
+			portdb = trees[myroot]["porttree"].dbapi
+			portdb.close_caches()
+			portdbapi.portdbapi_instances.remove(portdb)
+			del trees[myroot]["porttree"], myroot, portdb
+
+	settings = config(config_root=config_root, target_root=target_root,
+		config_incrementals=portage_const.INCREMENTALS)
+	settings.lock()
+	settings.validate()
+
+	myroots = [(settings["ROOT"], settings)]
+	if settings["ROOT"] != "/":
+		settings = config(config_root=None, target_root=None,
+			config_incrementals=portage_const.INCREMENTALS)
+		settings.lock()
+		settings.validate()
+		myroots.append((settings["ROOT"], settings))
+
+	for myroot, mysettings in myroots:
+		trees[myroot] = portage_util.LazyItemsDict(trees.get(myroot, None))
+		trees[myroot].addLazySingleton("virtuals", mysettings.getvirtuals, myroot)
+		trees[myroot].addLazySingleton(
+			"vartree", vartree, myroot, categories=mysettings.categories,
+				settings=mysettings)
+		trees[myroot].addLazySingleton("porttree",
+			portagetree, myroot, settings=mysettings)
+		trees[myroot].addLazySingleton("bintree",
+			binarytree, myroot, mysettings["PKGDIR"], settings=mysettings)
+	return trees
+
+# Initialization of legacy globals.  No functions/classes below this point
+# please!  When the above functions and classes become independent of the
+# below global variables, it will be possible to make the below code
+# conditional on a backward compatibility flag (backward compatibility could
+# be disabled via an environment variable, for example).  This will enable new
+# code that is aware of this flag to import portage without the unnecessary
+# overhead (and other issues!) of initializing the legacy globals.
+
+def init_legacy_globals():
+	global db, settings, root, portdb, selinux_enabled, mtimedbfile, mtimedb, \
+	archlist, features, groups, pkglines, thirdpartymirrors, usedefaults, \
+	profiledir, flushmtimedb
+
+	# Portage needs to ensure a sane umask for the files it creates.
+	os.umask(022)
+
+	kwargs = {}
+	for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):
+		kwargs[k] = os.environ.get(envvar, "/")
+
+	db = create_trees(**kwargs)
+
+	settings = db["/"]["vartree"].settings
+	portdb = db["/"]["porttree"].dbapi
+
+	for myroot in db:
+		if myroot != "/":
+			settings = db[myroot]["vartree"].settings
+			portdb = db[myroot]["porttree"].dbapi
+			break
+
+	root = settings["ROOT"]
+
+	mtimedbfile = os.path.join("/", CACHE_PATH.lstrip(os.path.sep), "mtimedb")
+	mtimedb = MtimeDB(mtimedbfile)
+
+	# ========================================================================
+	# COMPATIBILITY
+	# These attributes should not be used
+	# within Portage under any circumstances.
+	# ========================================================================
+	archlist    = settings.archlist()
+	features    = settings.features
+	groups      = settings["ACCEPT_KEYWORDS"].split()
+	pkglines    = settings.packages
+	selinux_enabled   = settings.selinux_enabled()
+	thirdpartymirrors = settings.thirdpartymirrors()
+	usedefaults       = settings.use_defs
+	profiledir  = None
+	if os.path.isdir(PROFILE_PATH):
+		profiledir = PROFILE_PATH
+	def flushmtimedb(record):
+		writemsg("portage.flushmtimedb() is DEPRECATED\n")
+	# ========================================================================
+	# COMPATIBILITY
+	# These attributes should not be used
+	# within Portage under any circumstances.
+	# ========================================================================
+
+# WARNING!
+# The PORTAGE_LEGACY_GLOBALS environment variable is reserved for internal
+# use within Portage.  External use of this variable is unsupported because
+# it is experimental and it's behavior is likely to change.
+if "PORTAGE_LEGACY_GLOBALS" not in os.environ:
+	init_legacy_globals()
+
+# Clear the cache
+dircache={}
+
+# ============================================================================
+# ============================================================================
+
Index: /vendor/portage/current/pym/portage_checksum.py
===================================================================
--- /vendor/portage/current/pym/portage_checksum.py	(revision 3419)
+++ /vendor/portage/current/pym/portage_checksum.py	(revision 3419)
@@ -0,0 +1,242 @@
+# portage_checksum.py -- core Portage functionality
+# Copyright 1998-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: portage_checksum.py 5031 2006-11-14 02:29:54Z zmedico $
+
+if not hasattr(__builtins__, "set"):
+	from sets import Set as set
+
+from portage_const import PRIVATE_PATH,PRELINK_BINARY,HASHING_BLOCKSIZE
+import os
+import errno
+import shutil
+import stat
+import portage_exception
+import portage_exec
+import portage_util
+import portage_locks
+import commands
+import sha
+
+
+# actual hash functions first
+
+#dict of all available hash functions
+hashfunc_map = {}
+
+# We _try_ to load this module. If it fails we do the slightly slower fallback.
+try:
+	import fchksum
+	
+	def md5hash(filename):
+		return fchksum.fmd5t(filename)
+
+except ImportError:
+	import md5
+	def md5hash(filename):
+		return pyhash(filename, md5)
+hashfunc_map["MD5"] = md5hash
+
+def sha1hash(filename):
+	return pyhash(filename, sha)
+hashfunc_map["SHA1"] = sha1hash
+	
+# Keep pycrypto optional for now, there are no internal fallbacks for these
+try:
+	import Crypto.Hash.SHA256
+	
+	def sha256hash(filename):
+		return pyhash(filename, Crypto.Hash.SHA256)
+	hashfunc_map["SHA256"] = sha256hash
+except ImportError:
+	pass
+
+try:
+	import Crypto.Hash.RIPEMD
+	
+	def rmd160hash(filename):
+		return pyhash(filename, Crypto.Hash.RIPEMD)
+	hashfunc_map["RMD160"] = rmd160hash
+except ImportError:
+	pass
+
+def getsize(filename):
+	size = os.stat(filename).st_size
+	return (size, size)
+hashfunc_map["size"] = getsize
+
+# end actual hash functions
+
+prelink_capable = False
+if os.path.exists(PRELINK_BINARY):
+	results = commands.getstatusoutput(PRELINK_BINARY+" --version > /dev/null 2>&1")
+	if (results[0] >> 8) == 0:
+		prelink_capable=1
+	del results
+
+def perform_md5(x, calc_prelink=0):
+	return perform_checksum(x, "MD5", calc_prelink)[0]
+
+def perform_all(x, calc_prelink=0):
+	mydict = {}
+	for k in hashfunc_map.keys():
+		mydict[k] = perform_checksum(x, hashfunc_map[k], calc_prelink)[0]
+	return mydict
+
+def get_valid_checksum_keys():
+	return hashfunc_map.keys()
+
+def verify_all(filename, mydict, calc_prelink=0, strict=0):
+	"""
+	Verify all checksums against a file.
+
+	@param filename: File to run the checksums against
+	@type filename: String
+	@param calc_prelink: Whether or not to reverse prelink before running the checksum
+	@type calc_prelink: Integer
+	@param strict: Enable/Disable strict checking (which stops exactly at a checksum failure and throws an exception)
+	@type strict: Integer
+	@rtype: Tuple
+	@return: Result of the checks and possible message:
+		1) If size fails, False, and a tuple containing a message, the given size, and the actual size
+		2) If there is an os error, False, and a tuple containing the system error followed by 2 nulls
+		3) If a checksum fails, False and a tuple containing a message, the given hash, and the actual hash
+		4) If all checks succeed, return True and a fake reason
+	"""
+	# Dict relates to single file only.
+	# returns: (passed,reason)
+	file_is_ok = True
+	reason     = "Reason unknown"
+	try:
+		mysize = os.stat(filename)[stat.ST_SIZE]
+		if mydict["size"] != mysize:
+			return False,("Filesize does not match recorded size", mysize, mydict["size"])
+	except OSError, e:
+		if e.errno == errno.ENOENT:
+			raise portage_exception.FileNotFound(filename)
+		return False, (str(e), None, None)
+
+	verifiable_hash_types = set(mydict).intersection(hashfunc_map)
+	verifiable_hash_types.discard("size")
+	if not verifiable_hash_types:
+		expected = set(hashfunc_map)
+		expected.discard("size")
+		expected = list(expected)
+		expected.sort()
+		expected = " ".join(expected)
+		got = set(mydict)
+		got.discard("size")
+		got = list(got)
+		got.sort()
+		got = " ".join(got)
+		return False, ("Insufficient data for checksum verification", got, expected)
+
+	for x in mydict.keys():
+		if   x == "size":
+			continue
+		elif x in hashfunc_map.keys():
+			myhash = perform_checksum(filename, x, calc_prelink=calc_prelink)[0]
+			if mydict[x] != myhash:
+				if strict:
+					raise portage_exception.DigestException, "Failed to verify '$(file)s' on checksum type '%(type)s'" % {"file":filename, "type":x}
+				else:
+					file_is_ok = False
+					reason     = (("Failed on %s verification" % x), myhash,mydict[x])
+					break
+	return file_is_ok,reason
+
+def pyhash(filename, hashobject):
+	"""
+	Run a checksum against a file.
+
+	@param filename: File to run the checksum against
+	@type filename: String
+	@param hashname: The hash object that will execute the checksum on the file
+	@type hashname: Object
+	@return: The hash and size of the data
+	"""
+	f = open(filename, 'rb')
+	blocksize = HASHING_BLOCKSIZE
+	data = f.read(blocksize)
+	size = 0L
+	sum = hashobject.new()
+	while data:
+		sum.update(data)
+		size = size + len(data)
+		data = f.read(blocksize)
+	f.close()
+
+	return (sum.hexdigest(), size)
+
+def perform_checksum(filename, hashname="MD5", calc_prelink=0):
+	"""
+	Run a specific checksum against a file.
+
+	@param filename: File to run the checksum against
+	@type filename: String
+	@param hashname: The type of hash function to run
+	@type hashname: String
+	@param calc_prelink: Whether or not to reverse prelink before running the checksum
+	@type calc_prelink: Integer
+	@rtype: Tuple
+	@return: The hash and size of the data
+	"""
+	global prelink_capable
+	myfilename      = filename[:]
+	prelink_tmpfile = os.path.join("/", PRIVATE_PATH, "prelink-checksum.tmp." + str(os.getpid()))
+	mylock          = None
+	try:
+		if calc_prelink and prelink_capable:
+			mylock = portage_locks.lockfile(prelink_tmpfile, wantnewlockfile=1)
+			# Create non-prelinked temporary file to checksum.
+			# Files rejected by prelink are summed in place.
+			try:
+				retval = portage_exec.spawn([PRELINK_BINARY, "--undo", "-o",
+					prelink_tmpfile, filename], fd_pipes={})
+				if retval == os.EX_OK:
+					myfilename = prelink_tmpfile
+			except portage_exception.CommandNotFound:
+				# This happens during uninstallation of prelink.
+				prelink_capable = False
+		try:
+			if hashname not in hashfunc_map:
+				raise portage_exception.DigestException(hashname + \
+					" hash function not available (needs dev-python/pycrypto)")
+			myhash, mysize = hashfunc_map[hashname](myfilename)
+		except (OSError, IOError), e:
+			if e.errno == errno.ENOENT:
+				raise portage_exception.FileNotFound(myfilename)
+			raise
+		if calc_prelink and prelink_capable:
+			try:
+				os.unlink(prelink_tmpfile)
+			except OSError, e:
+				if e.errno != errno.ENOENT:
+					raise
+				del e
+		return myhash, mysize
+	finally:
+		if mylock:
+			portage_locks.unlockfile(mylock)
+
+def perform_multiple_checksums(filename, hashes=["MD5"], calc_prelink=0):
+	"""
+	Run a group of checksums against a file.
+
+	@param filename: File to run the checksums against
+	@type filename: String
+	@param hashes: A list of checksum functions to run against the file
+	@type hashname: List
+	@param calc_prelink: Whether or not to reverse prelink before running the checksum
+	@type calc_prelink: Integer
+	@rtype: Tuple
+	@return: A dictionary in the form:
+		return_value[hash_name] = (hash_result,size)
+		for each given checksum
+	"""
+	rVal = {}
+	for x in hashes:
+		if x not in hashfunc_map:
+			raise portage_exception.DigestException, x+" hash function not available (needs dev-python/pycrypto)"
+		rVal[x] = perform_checksum(filename, x, calc_prelink)[0]
+	return rVal
Index: /vendor/portage/current/pym/portage_checksum.py.orig
===================================================================
--- /vendor/portage/current/pym/portage_checksum.py.orig	(revision 3419)
+++ /vendor/portage/current/pym/portage_checksum.py.orig	(revision 3419)
@@ -0,0 +1,219 @@
+# portage_checksum.py -- core Portage functionality
+# Copyright 1998-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: portage_checksum.py 5031 2006-11-14 02:29:54Z zmedico $
+
+
+from portage_const import PRIVATE_PATH,PRELINK_BINARY,HASHING_BLOCKSIZE
+import os
+import errno
+import shutil
+import stat
+import portage_exception
+import portage_exec
+import portage_util
+import portage_locks
+import commands
+import sha
+
+
+# actual hash functions first
+
+#dict of all available hash functions
+hashfunc_map = {}
+
+# We _try_ to load this module. If it fails we do the slightly slower fallback.
+try:
+	import fchksum
+	
+	def md5hash(filename):
+		return fchksum.fmd5t(filename)
+
+except ImportError:
+	import md5
+	def md5hash(filename):
+		return pyhash(filename, md5)
+hashfunc_map["MD5"] = md5hash
+
+def sha1hash(filename):
+	return pyhash(filename, sha)
+hashfunc_map["SHA1"] = sha1hash
+	
+# Keep pycrypto optional for now, there are no internal fallbacks for these
+try:
+	import Crypto.Hash.SHA256
+	
+	def sha256hash(filename):
+		return pyhash(filename, Crypto.Hash.SHA256)
+	hashfunc_map["SHA256"] = sha256hash
+except ImportError:
+	pass
+
+try:
+	import Crypto.Hash.RIPEMD
+	
+	def rmd160hash(filename):
+		return pyhash(filename, Crypto.Hash.RIPEMD)
+	hashfunc_map["RMD160"] = rmd160hash
+except ImportError:
+	pass
+
+def getsize(filename):
+	size = os.stat(filename).st_size
+	return (size, size)
+hashfunc_map["size"] = getsize
+
+# end actual hash functions
+
+prelink_capable = False
+if os.path.exists(PRELINK_BINARY):
+	results = commands.getstatusoutput(PRELINK_BINARY+" --version > /dev/null 2>&1")
+	if (results[0] >> 8) == 0:
+		prelink_capable=1
+	del results
+
+def perform_md5(x, calc_prelink=0):
+	return perform_checksum(x, "MD5", calc_prelink)[0]
+
+def perform_all(x, calc_prelink=0):
+	mydict = {}
+	for k in hashfunc_map.keys():
+		mydict[k] = perform_checksum(x, hashfunc_map[k], calc_prelink)[0]
+	return mydict
+
+def get_valid_checksum_keys():
+	return hashfunc_map.keys()
+
+def verify_all(filename, mydict, calc_prelink=0, strict=0):
+	"""
+	Verify all checksums against a file.
+
+	@param filename: File to run the checksums against
+	@type filename: String
+	@param calc_prelink: Whether or not to reverse prelink before running the checksum
+	@type calc_prelink: Integer
+	@param strict: Enable/Disable strict checking (which stops exactly at a checksum failure and throws an exception)
+	@type strict: Integer
+	@rtype: Tuple
+	@return: Result of the checks and possible message:
+		1) If size fails, False, and a tuple containing a message, the given size, and the actual size
+		2) If there is an os error, False, and a tuple containing the system error followed by 2 nulls
+		3) If a checksum fails, False and a tuple containing a message, the given hash, and the actual hash
+		4) If all checks succeed, return True and a fake reason
+	"""
+	# Dict relates to single file only.
+	# returns: (passed,reason)
+	file_is_ok = True
+	reason     = "Reason unknown"
+	try:
+		mysize = os.stat(filename)[stat.ST_SIZE]
+		if mydict["size"] != mysize:
+			return False,("Filesize does not match recorded size", mysize, mydict["size"])
+	except OSError, e:
+		if e.errno == errno.ENOENT:
+			raise portage_exception.FileNotFound(filename)
+		return False, (str(e), None, None)
+	for x in mydict.keys():
+		if   x == "size":
+			continue
+		elif x in hashfunc_map.keys():
+			myhash = perform_checksum(filename, x, calc_prelink=calc_prelink)[0]
+			if mydict[x] != myhash:
+				if strict:
+					raise portage_exception.DigestException, "Failed to verify '$(file)s' on checksum type '%(type)s'" % {"file":filename, "type":x}
+				else:
+					file_is_ok = False
+					reason     = (("Failed on %s verification" % x), myhash,mydict[x])
+					break
+	return file_is_ok,reason
+
+def pyhash(filename, hashobject):
+	"""
+	Run a checksum against a file.
+
+	@param filename: File to run the checksum against
+	@type filename: String
+	@param hashname: The hash object that will execute the checksum on the file
+	@type hashname: Object
+	@return: The hash and size of the data
+	"""
+	f = open(filename, 'rb')
+	blocksize = HASHING_BLOCKSIZE
+	data = f.read(blocksize)
+	size = 0L
+	sum = hashobject.new()
+	while data:
+		sum.update(data)
+		size = size + len(data)
+		data = f.read(blocksize)
+	f.close()
+
+	return (sum.hexdigest(), size)
+
+def perform_checksum(filename, hashname="MD5", calc_prelink=0):
+	"""
+	Run a specific checksum against a file.
+
+	@param filename: File to run the checksum against
+	@type filename: String
+	@param hashname: The type of hash function to run
+	@type hashname: String
+	@param calc_prelink: Whether or not to reverse prelink before running the checksum
+	@type calc_prelink: Integer
+	@rtype: Tuple
+	@return: The hash and size of the data
+	"""
+	myfilename      = filename[:]
+	prelink_tmpfile = os.path.join("/", PRIVATE_PATH, "prelink-checksum.tmp." + str(os.getpid()))
+	mylock          = None
+	try:
+		if calc_prelink and prelink_capable:
+			mylock = portage_locks.lockfile(prelink_tmpfile, wantnewlockfile=1)
+			# Create non-prelinked temporary file to checksum.
+			# Files rejected by prelink are summed in place.
+			retval = portage_exec.spawn([PRELINK_BINARY, "--undo", "-o",
+				prelink_tmpfile, filename], fd_pipes={})
+			if retval == os.EX_OK:
+				myfilename = prelink_tmpfile
+		try:
+			if hashname not in hashfunc_map:
+				raise portage_exception.DigestException(hashname + \
+					" hash function not available (needs dev-python/pycrypto)")
+			myhash, mysize = hashfunc_map[hashname](myfilename)
+		except (OSError, IOError), e:
+			if e.errno == errno.ENOENT:
+				raise portage_exception.FileNotFound(myfilename)
+			raise
+		if calc_prelink and prelink_capable:
+			try:
+				os.unlink(prelink_tmpfile)
+			except OSError, e:
+				if e.errno != errno.ENOENT:
+					raise
+				del e
+		return myhash, mysize
+	finally:
+		if mylock:
+			portage_locks.unlockfile(mylock)
+
+def perform_multiple_checksums(filename, hashes=["MD5"], calc_prelink=0):
+	"""
+	Run a group of checksums against a file.
+
+	@param filename: File to run the checksums against
+	@type filename: String
+	@param hashes: A list of checksum functions to run against the file
+	@type hashname: List
+	@param calc_prelink: Whether or not to reverse prelink before running the checksum
+	@type calc_prelink: Integer
+	@rtype: Tuple
+	@return: A dictionary in the form:
+		return_value[hash_name] = (hash_result,size)
+		for each given checksum
+	"""
+	rVal = {}
+	for x in hashes:
+		if x not in hashfunc_map:
+			raise portage_exception.DigestException, x+" hash function not available (needs dev-python/pycrypto)"
+		rVal[x] = perform_checksum(filename, x, calc_prelink)[0]
+	return rVal
Index: /vendor/portage/current/pym/portage_const.py
===================================================================
--- /vendor/portage/current/pym/portage_const.py	(revision 3419)
+++ /vendor/portage/current/pym/portage_const.py	(revision 3419)
@@ -0,0 +1,61 @@
+# portage: Constants
+# Copyright 1998-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: portage_const.py 5493 2007-01-09 02:18:21Z antarus $
+
+
+# ===========================================================================
+# START OF CONSTANTS -- START OF CONSTANTS -- START OF CONSTANTS -- START OF
+# ===========================================================================
+
+import os
+
+VDB_PATH                = "var/db/pkg"
+PRIVATE_PATH            = "var/lib/portage"
+CACHE_PATH              = "/var/cache/edb"
+DEPCACHE_PATH           = CACHE_PATH+"/dep"
+
+USER_CONFIG_PATH        = "/etc/portage"
+MODULES_FILE_PATH       = USER_CONFIG_PATH+"/modules"
+CUSTOM_PROFILE_PATH     = USER_CONFIG_PATH+"/profile"
+
+#PORTAGE_BASE_PATH       = "/usr/lib/portage"
+PORTAGE_BASE_PATH       = os.path.join(os.sep, os.sep.join(__file__.split(os.sep)[:-2]))
+PORTAGE_BIN_PATH        = PORTAGE_BASE_PATH+"/bin"
+PORTAGE_PYM_PATH        = PORTAGE_BASE_PATH+"/pym"
+PROFILE_PATH            = "/etc/make.profile"
+LOCALE_DATA_PATH        = PORTAGE_BASE_PATH+"/locale"
+
+EBUILD_SH_BINARY        = PORTAGE_BIN_PATH+"/ebuild.sh"
+MISC_SH_BINARY          = PORTAGE_BIN_PATH + "/misc-functions.sh"
+SANDBOX_BINARY          = "/usr/bin/sandbox"
+BASH_BINARY             = "/bin/bash"
+MOVE_BINARY             = "/bin/mv"
+PRELINK_BINARY          = "/usr/sbin/prelink"
+
+WORLD_FILE              = PRIVATE_PATH + "/world"
+MAKE_CONF_FILE          = "/etc/make.conf"
+MAKE_DEFAULTS_FILE      = PROFILE_PATH + "/make.defaults"
+DEPRECATED_PROFILE_FILE = PROFILE_PATH+"/deprecated"
+USER_VIRTUALS_FILE      = USER_CONFIG_PATH+"/virtuals"
+EBUILD_SH_ENV_FILE      = USER_CONFIG_PATH+"/bashrc"
+INVALID_ENV_FILE        = "/etc/spork/is/not/valid/profile.env"
+CUSTOM_MIRRORS_FILE     = USER_CONFIG_PATH+"/mirrors"
+CONFIG_MEMORY_FILE      = PRIVATE_PATH + "/config"
+COLOR_MAP_FILE          = USER_CONFIG_PATH + "/color.map"
+
+INCREMENTALS=["USE","USE_EXPAND","USE_EXPAND_HIDDEN","FEATURES","ACCEPT_KEYWORDS","ACCEPT_LICENSE","CONFIG_PROTECT_MASK","CONFIG_PROTECT","PRELINK_PATH","PRELINK_PATH_MASK"]
+EBUILD_PHASES           = ["setup", "unpack", "compile", "test", "install",
+                          "preinst", "postinst", "prerm", "postrm", "other"]
+
+EAPI = 0
+
+HASHING_BLOCKSIZE        = 32768
+MANIFEST1_HASH_FUNCTIONS = ["MD5","SHA256","RMD160"]
+MANIFEST2_HASH_FUNCTIONS = ["SHA1","SHA256","RMD160"]
+MANIFEST2_REQUIRED_HASH = "SHA1"
+
+MANIFEST2_IDENTIFIERS = ["AUX","MISC","DIST","EBUILD"]
+# ===========================================================================
+# END OF CONSTANTS -- END OF CONSTANTS -- END OF CONSTANTS -- END OF CONSTANT
+# ===========================================================================
Index: /vendor/portage/current/pym/portage_data.py
===================================================================
--- /vendor/portage/current/pym/portage_data.py	(revision 3419)
+++ /vendor/portage/current/pym/portage_data.py	(revision 3419)
@@ -0,0 +1,126 @@
+# portage_data.py -- Calculated/Discovered Data Values
+# Copyright 1998-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: portage_data.py 5462 2007-01-04 21:18:13Z zmedico $
+
+if not hasattr(__builtins__, "set"):
+	from sets import Set as set
+
+import os, sys, pwd, grp
+from portage_util import writemsg
+from output import green,red
+from output import create_color_func
+bad = create_color_func("BAD")
+
+ostype=os.uname()[0]
+
+lchown = None
+if ostype=="Linux" or ostype.lower().endswith("gnu"):
+	userland="GNU"
+	os.environ["XARGS"]="xargs -r"
+elif ostype == "Darwin":
+	userland="Darwin"
+	os.environ["XARGS"]="xargs"
+	def lchown(*pos_args, **key_args):
+		pass
+elif ostype.endswith("BSD") or ostype =="DragonFly":
+	userland="BSD"
+	os.environ["XARGS"]="xargs"
+else:
+	writemsg(red("Operating system")+" \""+ostype+"\" "+red("currently unsupported. Exiting.")+"\n")
+	sys.exit(1)
+
+if not lchown:
+	if "lchown" in dir(os):
+		# Included in python-2.3
+		lchown = os.lchown
+	else:
+		try:
+			import missingos
+			lchown = missingos.lchown
+		except ImportError:
+			def lchown(*pos_args, **key_args):
+				writemsg(red("!!!") + " It seems that os.lchown does not" + \
+					" exist.  Please rebuild python.\n", noiselevel=-1)
+			lchown()
+
+os.environ["USERLAND"]=userland
+
+def portage_group_warning():
+	warn_prefix = bad("*** WARNING ***  ")
+	mylines = [
+		"For security reasons, only system administrators should be",
+		"allowed in the portage group.  Untrusted users or processes",
+		"can potentially exploit the portage group for attacks such as",
+		"local privilege escalation."
+	]
+	for x in mylines:
+		writemsg(warn_prefix, noiselevel=-1)
+		writemsg(x, noiselevel=-1)
+		writemsg("\n", noiselevel=-1)
+	writemsg("\n", noiselevel=-1)
+
+# Portage has 3 security levels that depend on the uid and gid of the main
+# process and are assigned according to the following table:
+#
+# Privileges  secpass  uid    gid
+# normal      0        any    any
+# group       1        any    portage_gid
+# super       2        0      any
+#
+# If the "wheel" group does not exist then wheelgid falls back to 0.
+# If the "portage" group does not exist then portage_uid falls back to wheelgid.
+
+secpass=0
+
+uid=os.getuid()
+wheelgid=0
+
+if uid==0:
+	secpass=2
+try:
+	wheelgid=grp.getgrnam("wheel")[2]
+except KeyError:
+	writemsg("portage initialization: your system doesn't have a 'wheel' group.\n")
+	writemsg("Please fix this as it is a normal system requirement. 'wheel' is GID 10\n")
+	writemsg("`emerge baselayout` and a config update with dispatch-conf, etc-update\n")
+	writemsg("or cfg-update should remedy this problem.\n")
+	pass
+
+#Discover the uid and gid of the portage user/group
+try:
+	portage_uid=pwd.getpwnam("portage")[2]
+	portage_gid=grp.getgrnam("portage")[2]
+	if secpass < 1 and portage_gid in os.getgroups():
+		secpass=1
+except KeyError:
+	portage_uid=0
+	portage_gid=0
+	writemsg("\n")
+	writemsg(  red("portage: 'portage' user or group missing. Please update baselayout\n"))
+	writemsg(  red("         and merge portage user(250) and group(250) into your passwd\n"))
+	writemsg(  red("         and group files. Non-root compilation is disabled until then.\n"))
+	writemsg(      "         Also note that non-root/wheel users will need to be added to\n")
+	writemsg(      "         the portage group to do portage commands.\n")
+	writemsg("\n")
+	writemsg(      "         For the defaults, line 1 goes into passwd, and 2 into group.\n")
+	writemsg(green("         portage:x:250:250:portage:/var/tmp/portage:/bin/false\n"))
+	writemsg(green("         portage::250:portage\n"))
+	writemsg("\n")
+	portage_group_warning()
+
+userpriv_groups = [portage_gid]
+if secpass >= 2:
+	# Get a list of group IDs for the portage user.  Do not use grp.getgrall()
+	# since it is known to trigger spurious SIGPIPE problems with nss_ldap.
+	from commands import getstatusoutput
+	mystatus, myoutput = getstatusoutput("id -G portage")
+	if mystatus == os.EX_OK:
+		for x in myoutput.split():
+			try:
+				userpriv_groups.append(int(x))
+			except ValueError:
+				pass
+			del x
+		userpriv_groups = list(set(userpriv_groups))
+	del getstatusoutput, mystatus, myoutput
Index: /vendor/portage/current/pym/portage_debug.py
===================================================================
--- /vendor/portage/current/pym/portage_debug.py	(revision 3419)
+++ /vendor/portage/current/pym/portage_debug.py	(revision 3419)
@@ -0,0 +1,115 @@
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+import os, sys, threading
+
+import portage_const
+from portage_util import writemsg
+
+def set_trace(on=True):
+	if on:
+		t = trace_handler()
+		threading.settrace(t.event_handler)
+		sys.settrace(t.event_handler)
+	else:
+		sys.settrace(None)
+		threading.settrace(None)
+
+class trace_handler(object):
+
+	def __init__(self):
+		python_system_paths = []
+		for x in sys.path:
+			if os.path.basename(x).startswith("python2."):
+				python_system_paths.append(x)
+
+		self.ignore_prefixes = []
+		for x in python_system_paths:
+			self.ignore_prefixes.append(x + os.sep)
+
+		self.trim_filename = prefix_trimmer(os.path.join(portage_const.PORTAGE_BASE_PATH, "pym") + os.sep).trim
+		self.show_local_lines = False
+		self.max_repr_length = 200
+
+	def event_handler(self, *args):
+		frame, event, arg = args
+		if "line" == event:
+			if self.show_local_lines:
+				self.trace_line(*args)
+		else:
+			if not self.ignore_filename(frame.f_code.co_filename):
+				self.trace_event(*args)
+				return self.event_handler
+
+	def trace_event(self, frame, event, arg):
+		writemsg("%s line=%d name=%s event=%s %slocals=%s\n" % \
+		(self.trim_filename(frame.f_code.co_filename),
+		frame.f_lineno,
+		frame.f_code.co_name,
+		event,
+		self.arg_repr(frame, event, arg),
+		self.locals_repr(frame, event, arg)))
+
+	def arg_repr(self, frame, event, arg):
+		my_repr = None
+		if "return" == event:
+			my_repr = repr(arg)
+			if len(my_repr) > self.max_repr_length:
+				my_repr = "'omitted'"
+			return "value=%s " % my_repr
+		elif "exception" == event:
+			my_repr = repr(arg[1])
+			if len(my_repr) > self.max_repr_length:
+				my_repr = "'omitted'"
+			return "type=%s value=%s " % (arg[0], my_repr)
+
+		return ""
+
+	def trace_line(self, frame, event, arg):
+		writemsg("%s line=%d\n" % (self.trim_filename(frame.f_code.co_filename), frame.f_lineno))
+
+	def ignore_filename(self, filename):
+		if filename:
+			for x in self.ignore_prefixes:
+				if filename.startswith(x):
+					return True
+		return False
+
+	def locals_repr(self, frame, event, arg):
+		"""Create a representation of the locals dict that is suitable for
+		tracing output."""
+
+		my_locals = frame.f_locals.copy()
+
+		# prevent unsafe  __repr__ call on self when __init__ is called
+		# (method calls aren't safe until after __init__  has completed).
+		if frame.f_code.co_name == "__init__" and "self" in my_locals:
+			my_locals["self"] = "omitted"
+
+		# We omit items that will lead to unreasonable bloat of the trace
+		# output (and resulting log file).
+		for k, v in my_locals.iteritems():
+			my_repr = repr(v)
+			if len(my_repr) > self.max_repr_length:
+				my_locals[k] = "omitted"
+		return my_locals
+
+class prefix_trimmer(object):
+	def __init__(self, prefix):
+		self.prefix = prefix
+		self.cut_index = len(prefix)
+		self.previous = None
+		self.previous_trimmed = None
+
+	def trim(self, s):
+		"""Remove a prefix from the string and return the result.
+		The previous result is automatically cached."""
+		if s == self.previous:
+			return self.previous_trimmed
+		else:
+			if s.startswith(self.prefix):
+				self.previous_trimmed = s[self.cut_index:]
+			else:
+				self.previous_trimmed = s
+			return self.previous_trimmed
Index: /vendor/portage/current/pym/portage_dep.py
===================================================================
--- /vendor/portage/current/pym/portage_dep.py	(revision 3419)
+++ /vendor/portage/current/pym/portage_dep.py	(revision 3419)
@@ -0,0 +1,647 @@
+# deps.py -- Portage dependency resolution functions
+# Copyright 2003-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: portage_dep.py 5602 2007-01-12 09:00:01Z antarus $
+
+
+# DEPEND SYNTAX:
+#
+# 'use?' only affects the immediately following word!
+# Nesting is the only legal way to form multiple '[!]use?' requirements.
+#
+# Where: 'a' and 'b' are use flags, and 'z' is a depend atom.
+#
+# "a? z"           -- If 'a' in [use], then b is valid.
+# "a? ( z )"       -- Syntax with parenthesis.
+# "a? b? z"        -- Deprecated.
+# "a? ( b? z )"    -- Valid
+# "a? ( b? ( z ) ) -- Valid
+#
+
+import re,  sys, types
+import portage_exception
+from portage_exception import InvalidData
+from portage_versions import catpkgsplit, catsplit, pkgcmp, pkgsplit, ververify
+
+def cpvequal(cpv1, cpv2):
+	split1 = catpkgsplit(cpv1)
+	split2 = catpkgsplit(cpv2)
+	
+	if not split1 or not split2:
+		raise portage_exception.PortageException("Invalid data '%s, %s', parameter was not a CPV" % (cpv1, cpv2))
+	
+	if split1[0] != split2[0]:
+		return False
+	
+	return (pkgcmp(split1[1:], split2[1:]) == 0)
+
+def strip_empty(myarr):
+	"""
+	Strip all empty elements from an array
+
+	@param myarr: The list of elements
+	@type myarr: List
+	@rtype: Array
+	@return: The array with empty elements removed
+	"""
+	for x in range(len(myarr)-1, -1, -1):
+		if not myarr[x]:
+			del myarr[x]
+	return myarr
+
+def paren_reduce(mystr,tokenize=1):
+	"""
+	Take a string and convert all paren enclosed entities into sublists, optionally
+	futher splitting the list elements by spaces.
+
+	Example usage:
+		>>> paren_reduce('foobar foo ( bar baz )',1)
+		['foobar', 'foo', ['bar', 'baz']]
+		>>> paren_reduce('foobar foo ( bar baz )',0)
+		['foobar foo ', [' bar baz ']]
+
+	@param mystr: The string to reduce
+	@type mystr: String
+	@param tokenize: Split on spaces to produces further list breakdown
+	@type tokenize: Integer
+	@rtype: Array
+	@return: The reduced string in an array
+	"""
+	mylist = []
+	while mystr:
+		if ("(" not in mystr) and (")" not in mystr):
+			freesec = mystr
+			subsec = None
+			tail = ""
+		elif mystr[0] == ")":
+			return [mylist,mystr[1:]]
+		elif ("(" in mystr) and (mystr.index("(") < mystr.index(")")):
+			freesec,subsec = mystr.split("(",1)
+			subsec,tail = paren_reduce(subsec,tokenize)
+		else:
+			subsec,tail = mystr.split(")",1)
+			if tokenize:
+				subsec = strip_empty(subsec.split(" "))
+				return [mylist+subsec,tail]
+			return mylist+[subsec],tail
+		mystr = tail
+		if freesec:
+			if tokenize:
+				mylist = mylist + strip_empty(freesec.split(" "))
+			else:
+				mylist = mylist + [freesec]
+		if subsec is not None:
+			mylist = mylist + [subsec]
+	return mylist
+
+def paren_enclose(mylist):
+	"""
+	Convert a list to a string with sublists enclosed with parens.
+
+	Example usage:
+		>>> test = ['foobar','foo',['bar','baz']]
+		>>> paren_enclose(test)
+		'foobar foo ( bar baz )'
+
+	@param mylist: The list
+	@type mylist: List
+	@rtype: String
+	@return: The paren enclosed string
+	"""
+	mystrparts = []
+	for x in mylist:
+		if isinstance(x, list):
+			mystrparts.append("( "+paren_enclose(x)+" )")
+		else:
+			mystrparts.append(x)
+	return " ".join(mystrparts)
+
+# This is just for use by emerge so that it can enable a backward compatibility
+# mode in order to gracefully deal with installed packages that have invalid
+# atoms or dep syntax.  For backward compatibility with api consumers, strict
+# behavior will be explicitly enabled as necessary.
+_dep_check_strict = False
+
+def use_reduce(deparray, uselist=[], masklist=[], matchall=0, excludeall=[]):
+	"""
+	Takes a paren_reduce'd array and reduces the use? conditionals out
+	leaving an array with subarrays
+
+	@param deparray: paren_reduce'd list of deps
+	@type deparray: List
+	@param uselist: List of use flags
+	@type uselist: List
+	@param masklist: List of masked flags
+	@type masklist: List
+	@param matchall: Resolve all conditional deps unconditionally.  Used by repoman
+	@type matchall: Integer
+	@rtype: List
+	@return: The use reduced depend array
+	"""
+	# Quick validity checks
+	for x in range(len(deparray)):
+		if deparray[x] in ["||","&&"]:
+			if len(deparray) - 1 == x or not isinstance(deparray[x+1], list):
+				raise portage_exception.InvalidDependString(deparray[x]+" missing atom list in \""+paren_enclose(deparray)+"\"")
+	if deparray and deparray[-1] and deparray[-1][-1] == "?":
+		raise portage_exception.InvalidDependString("Conditional without target in \""+paren_enclose(deparray)+"\"")
+
+	global _dep_check_strict
+
+	mydeparray = deparray[:]
+	rlist = []
+	while mydeparray:
+		head = mydeparray.pop(0)
+
+		if type(head) == types.ListType:
+			additions = use_reduce(head, uselist, masklist, matchall, excludeall)
+			if additions:
+				rlist.append(additions)
+			elif rlist and rlist[-1] == "||":
+			#XXX: Currently some DEPEND strings have || lists without default atoms.
+			#	raise portage_exception.InvalidDependString("No default atom(s) in \""+paren_enclose(deparray)+"\"")
+				rlist.append([])
+
+		else:
+			if head[-1] == "?": # Use reduce next group on fail.
+				# Pull any other use conditions and the following atom or list into a separate array
+				newdeparray = [head]
+				while isinstance(newdeparray[-1], str) and newdeparray[-1][-1] == "?":
+					if mydeparray:
+						newdeparray.append(mydeparray.pop(0))
+					else:
+						raise ValueError, "Conditional with no target."
+
+				# Deprecation checks
+				warned = 0
+				if len(newdeparray[-1]) == 0:
+					sys.stderr.write("Note: Empty target in string. (Deprecated)\n")
+					warned = 1
+				if len(newdeparray) != 2:
+					sys.stderr.write("Note: Nested use flags without parenthesis (Deprecated)\n")
+					warned = 1
+				if warned:
+					sys.stderr.write("  --> "+" ".join(map(str,[head]+newdeparray))+"\n")
+
+				# Check that each flag matches
+				ismatch = True
+				for head in newdeparray[:-1]:
+					head = head[:-1]
+					if head[0] == "!":
+						head_key = head[1:]
+						if not matchall and head_key in uselist or \
+							head_key in excludeall:
+							ismatch = False
+							break
+					elif head not in masklist:
+						if not matchall and head not in uselist:
+							ismatch = False
+							break
+					else:
+						ismatch = False
+
+				# If they all match, process the target
+				if ismatch:
+					target = newdeparray[-1]
+					if isinstance(target, list):
+						additions = use_reduce(target, uselist, masklist, matchall, excludeall)
+						if additions:
+							rlist.append(additions)
+					elif not _dep_check_strict:
+						# The old deprecated behavior.
+						rlist.append(target)
+					else:
+						raise portage_exception.InvalidDependString(
+							"Conditional without parenthesis: '%s?'" % head)
+
+			else:
+				rlist += [head]
+
+	return rlist
+
+
+def dep_opconvert(deplist):
+	"""
+	Iterate recursively through a list of deps, if the
+	dep is a '||' or '&&' operator, combine it with the
+	list of deps that follows..
+
+	Example usage:
+		>>> test = ["blah", "||", ["foo", "bar", "baz"]]
+		>>> dep_opconvert(test)
+		['blah', ['||', 'foo', 'bar', 'baz']]
+
+	@param deplist: A list of deps to format
+	@type mydep: List
+	@rtype: List
+	@return:
+		The new list with the new ordering
+	"""
+
+	retlist = []
+	x = 0
+	while x != len(deplist):
+		if isinstance(deplist[x], list):
+			retlist.append(dep_opconvert(deplist[x]))
+		elif deplist[x] == "||" or deplist[x] == "&&":
+			retlist.append([deplist[x]] + dep_opconvert(deplist[x+1]))
+			x += 1
+		else:
+			retlist.append(deplist[x])
+		x += 1
+	return retlist
+
+def get_operator(mydep):
+	"""
+	Return the operator used in a depstring.
+
+	Example usage:
+		>>> from portage_dep import *
+		>>> get_operator(">=test-1.0")
+		'>='
+
+	@param mydep: The dep string to check
+	@type mydep: String
+	@rtype: String
+	@return: The operator. One of:
+		'~', '=', '>', '<', '=*', '>=', or '<='
+	"""
+	if mydep[0] == "~":
+		operator = "~"
+	elif mydep[0] == "=":
+		if mydep[-1] == "*":
+			operator = "=*"
+		else:
+			operator = "="
+	elif mydep[0] in "><":
+		if len(mydep) > 1 and mydep[1] == "=":
+			operator = mydep[0:2]
+		else:
+			operator = mydep[0]
+	else:
+		operator = None
+
+	return operator
+
+_dep_getcpv_cache = {}
+
+def dep_getcpv(mydep):
+	"""
+	Return the category-package-version with any operators/slot specifications stripped off
+
+	Example usage:
+		>>> dep_getcpv('>=media-libs/test-3.0')
+		'media-libs/test-3.0'
+
+	@param mydep: The depstring
+	@type mydep: String
+	@rtype: String
+	@return: The depstring with the operator removed
+	"""
+	global _dep_getcpv_cache
+	retval = _dep_getcpv_cache.get(mydep, None)
+	if retval is not None:
+		return retval
+	mydep_orig = mydep
+	if mydep and mydep[0] == "*":
+		mydep = mydep[1:]
+	if mydep and mydep[-1] == "*":
+		mydep = mydep[:-1]
+	if mydep and mydep[0] == "!":
+		mydep = mydep[1:]
+	if mydep[:2] in [">=", "<="]:
+		mydep = mydep[2:]
+	elif mydep[:1] in "=<>~":
+		mydep = mydep[1:]
+	colon = mydep.rfind(":")
+	if colon != -1:
+		mydep = mydep[:colon]
+	_dep_getcpv_cache[mydep_orig] = mydep
+	return mydep
+
+def dep_getslot(mydep):
+	"""
+	Retrieve the slot on a depend.
+
+	Example usage:
+		>>> dep_getslot('app-misc/test:3')
+		'3'
+
+	@param mydep: The depstring to retrieve the slot of
+	@type mydep: String
+	@rtype: String
+	@return: The slot
+	"""
+	colon = mydep.rfind(":")
+	if colon != -1:
+		return mydep[colon+1:]
+	return None
+
+_invalid_atom_chars_regexp = re.compile("[()|?]")
+
+def isvalidatom(atom, allow_blockers=False):
+	"""
+	Check to see if a depend atom is valid
+
+	Example usage:
+		>>> isvalidatom('media-libs/test-3.0')
+		0
+		>>> isvalidatom('>=media-libs/test-3.0')
+		1
+
+	@param atom: The depend atom to check against
+	@type atom: String
+	@rtype: Integer
+	@return: One of the following:
+		1) 0 if the atom is invalid
+		2) 1 if the atom is valid
+	"""
+	global _invalid_atom_chars_regexp
+	if _invalid_atom_chars_regexp.search(atom):
+		return 0
+	if allow_blockers and atom.startswith("!"):
+		atom = atom[1:]
+	try:
+		mycpv_cps = catpkgsplit(dep_getcpv(atom))
+	except InvalidData:
+		return 0
+	operator = get_operator(atom)
+	if operator:
+		if operator[0] in "<>" and atom[-1] == "*":
+			return 0
+		if mycpv_cps and mycpv_cps[0] != "null":
+			# >=cat/pkg-1.0
+			return 1
+		else:
+			# >=cat/pkg or >=pkg-1.0 (no category)
+			return 0
+	if mycpv_cps:
+		# cat/pkg-1.0
+		return 0
+
+	if (len(atom.split('/')) == 2):
+		# cat/pkg
+		return 1
+	else:
+		return 0
+
+def isjustname(mypkg):
+	"""
+	Checks to see if the depstring is only the package name (no version parts)
+
+	Example usage:
+		>>> isjustname('media-libs/test-3.0')
+		0
+		>>> isjustname('test')
+		1
+		>>> isjustname('media-libs/test')
+		1
+
+	@param mypkg: The package atom to check
+	@param mypkg: String
+	@rtype: Integer
+	@return: One of the following:
+		1) 0 if the package string is not just the package name
+		2) 1 if it is
+	"""
+	myparts = mypkg.split('-')
+	for x in myparts:
+		if ververify(x):
+			return 0
+	return 1
+
+iscache = {}
+
+def isspecific(mypkg):
+	"""
+	Checks to see if a package is in category/package-version or package-version format,
+	possibly returning a cached result.
+
+	Example usage:
+		>>> isspecific('media-libs/test')
+		0
+		>>> isspecific('media-libs/test-3.0')
+		1
+
+	@param mypkg: The package depstring to check against
+	@type mypkg: String
+	@rtype: Integer
+	@return: One of the following:
+		1) 0 if the package string is not specific
+		2) 1 if it is
+	"""
+	try:
+		return iscache[mypkg]
+	except KeyError:
+		pass
+	mysplit = mypkg.split("/")
+	if not isjustname(mysplit[-1]):
+			iscache[mypkg] = 1
+			return 1
+	iscache[mypkg] = 0
+	return 0
+
+def dep_getkey(mydep):
+	"""
+	Return the category/package-name of a depstring.
+
+	Example usage:
+		>>> dep_getkey('media-libs/test-3.0')
+		'media-libs/test'
+
+	@param mydep: The depstring to retrieve the category/package-name of
+	@type mydep: String
+	@rtype: String
+	@return: The package category/package-version
+	"""
+	mydep = dep_getcpv(mydep)
+	if mydep and isspecific(mydep):
+		mysplit = catpkgsplit(mydep)
+		if not mysplit:
+			return mydep
+		return mysplit[0] + "/" + mysplit[1]
+	else:
+		return mydep
+
+def match_to_list(mypkg, mylist):
+	"""
+	Searches list for entries that matches the package.
+
+	@param mypkg: The package atom to match
+	@type mypkg: String
+	@param mylist: The list of package atoms to compare against
+	@param mylist: List
+	@rtype: List
+	@return: A unique list of package atoms that match the given package atom
+	"""
+	matches = []
+	for x in mylist:
+		if match_from_list(x, [mypkg]):
+			if x not in matches:
+				matches.append(x)
+	return matches
+
+def best_match_to_list(mypkg, mylist):
+	"""
+	Returns the most specific entry that matches the package given.
+
+	@param mypkg: The package atom to check
+	@type mypkg: String
+	@param mylist: The list of package atoms to check against
+	@type mylist: List
+	@rtype: String
+	@return: The package atom which best matches given the following ordering:
+		- =cpv      6
+		- ~cpv      5
+		- =cpv*     4
+		- cp:slot   3
+		- >cpv      2
+		- <cpv      2
+		- >=cpv     2
+		- <=cpv     2
+		- cp        1
+	"""
+	operator_values = {'=':6, '~':5, '=*':4,
+		'>':2, '<':2, '>=':2, '<=':2, None:1}
+	maxvalue = 0
+	bestm  = None
+	for x in match_to_list(mypkg, mylist):
+		if dep_getslot(x) is not None:
+			if maxvalue < 3:
+				maxvalue = 3
+				bestm = x
+			continue
+		op_val = operator_values[get_operator(x)]
+		if op_val > maxvalue:
+			maxvalue = op_val
+			bestm  = x
+	return bestm
+
+_match_from_list_cache = {}
+
+def match_from_list(mydep, candidate_list):
+	"""
+	Searches list for entries that matches the package.
+
+	@param mydep: The package atom to match
+	@type mydep: String
+	@param candidate_list: The list of package atoms to compare against
+	@param candidate_list: List
+	@rtype: List
+	@return: A list of package atoms that match the given package atom
+	"""
+
+	global _match_from_list_cache
+	cache_key = (mydep, tuple(candidate_list))
+	mylist = _match_from_list_cache.get(cache_key, None)
+	if mylist is not None:
+		return mylist[:]
+
+	from portage_util import writemsg
+	if mydep[0] == "!":
+		mydep = mydep[1:]
+
+	mycpv     = dep_getcpv(mydep)
+	mycpv_cps = catpkgsplit(mycpv) # Can be None if not specific
+	slot      = None
+
+	if not mycpv_cps:
+		cat, pkg = catsplit(mycpv)
+		ver      = None
+		rev      = None
+		slot = dep_getslot(mydep)
+	else:
+		cat, pkg, ver, rev = mycpv_cps
+		if mydep == mycpv:
+			raise KeyError("Specific key requires an operator" + \
+				" (%s) (try adding an '=')" % (mydep))
+
+	if ver and rev:
+		operator = get_operator(mydep)
+		if not operator:
+			writemsg("!!! Invalid atom: %s\n" % mydep, noiselevel=-1)
+			return []
+	else:
+		operator = None
+
+	mylist = []
+
+	if operator is None:
+		for x in candidate_list:
+			xs = pkgsplit(x)
+			if xs is None:
+				xcpv = dep_getcpv(x)
+				if slot is not None:
+					xslot = dep_getslot(x)
+					if xslot is not None and xslot != slot:
+						"""  This function isn't given enough information to
+						reject atoms based on slot unless *both* compared atoms
+						specify slots."""
+						continue
+				if xcpv != mycpv:
+					continue
+			elif xs[0] != mycpv:
+				continue
+			mylist.append(x)
+
+	elif operator == "=": # Exact match
+		mylist = [cpv for cpv in candidate_list if cpvequal(cpv, mycpv)]
+
+	elif operator == "=*": # glob match
+		# XXX: Nasty special casing for leading zeros
+		# Required as =* is a literal prefix match, so can't 
+		# use vercmp
+		mysplit = catpkgsplit(mycpv)
+		myver = mysplit[2].lstrip("0")
+		if not myver or not myver[0].isdigit():
+			myver = "0"+myver
+		mycpv = mysplit[0]+"/"+mysplit[1]+"-"+myver
+		for x in candidate_list:
+			xs = catpkgsplit(x)
+			myver = xs[2].lstrip("0")
+			if not myver or not myver[0].isdigit():
+				myver = "0"+myver
+			xcpv = xs[0]+"/"+xs[1]+"-"+myver
+			if xcpv.startswith(mycpv):
+				mylist.append(x)
+
+	elif operator == "~": # version, any revision, match
+		for x in candidate_list:
+			xs = catpkgsplit(x)
+			if xs is None:
+				raise InvalidData(x)
+			if not cpvequal(xs[0]+"/"+xs[1]+"-"+xs[2], mycpv_cps[0]+"/"+mycpv_cps[1]+"-"+mycpv_cps[2]):
+				continue
+			if xs[2] != ver:
+				continue
+			mylist.append(x)
+
+	elif operator in [">", ">=", "<", "<="]:
+		mysplit = ["%s/%s" % (cat, pkg), ver, rev]
+		for x in candidate_list:
+			try:
+				result = pkgcmp(pkgsplit(x), mysplit)
+			except ValueError: # pkgcmp may return ValueError during int() conversion
+				writemsg("\nInvalid package name: %s\n" % x, noiselevel=-1)
+				raise
+			if result is None:
+				continue
+			elif operator == ">":
+				if result > 0:
+					mylist.append(x)
+			elif operator == ">=":
+				if result >= 0:
+					mylist.append(x)
+			elif operator == "<":
+				if result < 0:
+					mylist.append(x)
+			elif operator == "<=":
+				if result <= 0:
+					mylist.append(x)
+			else:
+				raise KeyError("Unknown operator: %s" % mydep)
+	else:
+		raise KeyError("Unknown operator: %s" % mydep)
+
+	_match_from_list_cache[cache_key] = mylist
+	return mylist
Index: /vendor/portage/current/pym/portage_exception.py
===================================================================
--- /vendor/portage/current/pym/portage_exception.py	(revision 3419)
+++ /vendor/portage/current/pym/portage_exception.py	(revision 3419)
@@ -0,0 +1,100 @@
+# Copyright 1998-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: portage_exception.py 5553 2007-01-11 17:34:56Z zmedico $
+
+
+class PortageException(Exception):
+	"""General superclass for portage exceptions"""
+	def __init__(self,value):
+		self.value = value[:]
+	def __str__(self):
+		if isinstance(self.value, basestring):
+			return self.value
+		else:
+			return repr(self.value)
+
+class CorruptionError(PortageException):
+	"""Corruption indication"""
+
+class InvalidDependString(PortageException):
+	"""An invalid depend string has been encountered"""
+
+class InvalidVersionString(PortageException):
+	"""An invalid version string has been encountered"""
+
+class SecurityViolation(PortageException):
+	"""An incorrect formatting was passed instead of the expected one"""
+
+class IncorrectParameter(PortageException):
+	"""A parameter of the wrong type was passed"""
+
+class MissingParameter(PortageException):
+	"""A parameter is required for the action requested but was not passed"""
+
+class ParseError(PortageException):
+	"""An error was generated while attempting to parse the request"""
+
+class InvalidData(PortageException):
+	"""An incorrect formatting was passed instead of the expected one"""
+
+class InvalidDataType(PortageException):
+	"""An incorrect type was passed instead of the expected one"""
+
+class InvalidLocation(PortageException):
+	"""Data was not found when it was expected to exist or was specified incorrectly"""
+
+class FileNotFound(InvalidLocation):
+	"""A file was not found when it was expected to exist"""
+
+class DirectoryNotFound(InvalidLocation):
+	"""A directory was not found when it was expected to exist"""
+
+class OperationNotPermitted(PortageException):
+	"""An operation was not permitted operating system"""
+
+class PermissionDenied(PortageException):
+	"""Permission denied"""
+
+class ReadOnlyFileSystem(PortageException):
+	"""Read-only file system"""
+
+class CommandNotFound(PortageException):
+	"""A required binary was not available or executable"""
+
+
+class PortagePackageException(PortageException):
+	"""Malformed or missing package data"""
+
+class PackageNotFound(PortagePackageException):
+	"""Missing Ebuild or Binary"""
+
+class InvalidPackageName(PortagePackageException):
+	"""Malformed package name"""
+
+class InvalidAtom(PortagePackageException):
+	"""Malformed atom spec"""
+
+class UnsupportedAPIException(PortagePackageException):
+	"""Unsupported API"""
+	def __init__(self, cpv, eapi):
+		self.cpv, self.eapi = cpv, eapi
+	def __str__(self):
+		return "Unable to do any operations on '%s', due to the fact it's EAPI is higher then this portage versions.  Please upgrade to a portage version that supports EAPI %s" % (self.cpv, self.eapi)
+
+
+
+class SignatureException(PortageException):
+	"""Signature was not present in the checked file"""
+
+class DigestException(SignatureException):
+	"""A problem exists in the digest"""
+
+class MissingSignature(SignatureException):
+	"""Signature was not present in the checked file"""
+
+class InvalidSignature(SignatureException):
+	"""Signature was checked and was not a valid, current, nor trusted signature"""
+
+class UntrustedSignature(SignatureException):
+	"""Signature was not certified to the desired security level"""
+
Index: /vendor/portage/current/pym/portage_exec.py
===================================================================
--- /vendor/portage/current/pym/portage_exec.py	(revision 3419)
+++ /vendor/portage/current/pym/portage_exec.py	(revision 3419)
@@ -0,0 +1,336 @@
+# portage.py -- core Portage functionality
+# Copyright 1998-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: portage_exec.py 5584 2007-01-12 04:07:38Z antarus $
+
+
+import os, atexit, signal, sys
+import portage_data
+
+from portage_util import dump_traceback
+from portage_const import BASH_BINARY, SANDBOX_BINARY
+from portage_exception import CommandNotFound
+
+try:
+	import resource
+	max_fd_limit = resource.getrlimit(resource.RLIMIT_NOFILE)[0]
+except ImportError:
+	max_fd_limit = 256
+
+if os.path.isdir("/proc/%i/fd" % os.getpid()):
+	def get_open_fds():
+		return map(int, [fd for fd in os.listdir("/proc/%i/fd" % os.getpid()) if fd.isdigit()])
+else:
+	def get_open_fds():
+		return xrange(max_fd_limit)
+
+sandbox_capable = (os.path.isfile(SANDBOX_BINARY) and
+                   os.access(SANDBOX_BINARY, os.X_OK))
+
+def spawn_bash(mycommand, debug=False, opt_name=None, **keywords):
+	"""
+	Spawns a bash shell running a specific commands
+	
+	@param mycommand: The command for bash to run
+	@type mycommand: String
+	@param debug: Turn bash debugging on (set -x)
+	@type debug: Boolean
+	@param opt_name: Name of the spawned process (detaults to binary name)
+	@type opt_name: String
+	@param keywords: Extra Dictionary arguments to pass to spawn
+	@type keywords: Dictionary
+	"""
+
+	args = [BASH_BINARY]
+	if not opt_name:
+		opt_name = os.path.basename(mycommand.split()[0])
+	if debug:
+		# Print commands and their arguments as they are executed.
+		args.append("-x")
+	args.append("-c")
+	args.append(mycommand)
+	return spawn(args, opt_name=opt_name, **keywords)
+
+def spawn_sandbox(mycommand, opt_name=None, **keywords):
+	if not sandbox_capable:
+		return spawn_bash(mycommand, opt_name=opt_name, **keywords)
+	args=[SANDBOX_BINARY]
+	if not opt_name:
+		opt_name = os.path.basename(mycommand.split()[0])
+	args.append(mycommand)
+	return spawn(args, opt_name=opt_name, **keywords)
+
+_exithandlers = []
+def atexit_register(func, *args, **kargs):
+	"""Wrapper around atexit.register that is needed in order to track
+	what is registered.  For example, when portage restarts itself via
+	os.execv, the atexit module does not work so we have to do it
+	manually by calling the run_exitfuncs() function in this module."""
+	_exithandlers.append((func, args, kargs))
+
+def run_exitfuncs():
+	"""This should behave identically to the routine performed by
+	the atexit module at exit time.  It's only necessary to call this
+	function when atexit will not work (because of os.execv, for
+	example)."""
+
+	# This function is a copy of the private atexit._run_exitfuncs()
+	# from the python 2.4.2 sources.  The only difference from the
+	# original function is in the output to stderr.
+	exc_info = None
+	while _exithandlers:
+		func, targs, kargs = _exithandlers.pop()
+		try:
+			func(*targs, **kargs)
+		except SystemExit:
+			exc_info = sys.exc_info()
+		except: # No idea what they called, so we need this broad except here.
+			dump_traceback("Error in portage_exec.run_exitfuncs", noiselevel=0)
+			exc_info = sys.exc_info()
+
+	if exc_info is not None:
+		raise exc_info[0], exc_info[1], exc_info[2]
+
+atexit.register(run_exitfuncs)
+
+# We need to make sure that any processes spawned are killed off when
+# we exit. spawn() takes care of adding and removing pids to this list
+# as it creates and cleans up processes.
+spawned_pids = []
+def cleanup():
+	while spawned_pids:
+		pid = spawned_pids.pop()
+		try:
+			if os.waitpid(pid, os.WNOHANG) == (0, 0):
+				os.kill(pid, signal.SIGTERM)
+				os.waitpid(pid, 0)
+		except OSError:
+			# This pid has been cleaned up outside
+			# of spawn().
+			pass
+
+atexit_register(cleanup)
+
+def spawn(mycommand, env={}, opt_name=None, fd_pipes=None, returnpid=False,
+          uid=None, gid=None, groups=None, umask=None, logfile=None,
+          path_lookup=True):
+	"""
+	Spawns a given command.
+	
+	@param mycommand: the command to execute
+	@type mycommand: String or List (Popen style list)
+	@param env: A dict of Key=Value pairs for env variables
+	@type env: Dictionary
+	@param opt_name: an optional name for the spawn'd process (defaults to the binary name)
+	@type opt_name: String
+	@param fd_pipes: A dict of mapping for pipes, { '0': stdin, '1': stdout } for example
+	@type fd_pipes: Dictionary
+	@param returnpid: Return the Process IDs for a successful spawn.
+	NOTE: This requires the caller clean up all the PIDs, otherwise spawn will clean them.
+	@type returnpid: Boolean
+	@param uid: User ID to spawn as; useful for dropping privilages
+	@type uid: Integer
+	@param gid: Group ID to spawn as; useful for dropping privilages
+	@type gid: Integer
+	@param groups: Group ID's to spawn in: useful for having the process run in multiple group contexts.
+	@type groups: List
+	@param umask: An integer representing the umask for the process (see man chmod for umask details)
+	@type umask: Integer
+	@param logfile: name of a file to use for logging purposes
+	@type logfile: String
+	@param path_lookup: If the binary is not fully specified then look for it in PATH
+	@type path_lookup: Boolean
+	
+	logfile requires stdout and stderr to be assigned to this process (ie not pointed
+	   somewhere else.)
+	
+	"""
+
+	# mycommand is either a str or a list
+	if isinstance(mycommand, str):
+		mycommand = mycommand.split()
+
+	# If an absolute path to an executable file isn't given
+	# search for it unless we've been told not to.
+	binary = mycommand[0]
+	if (not os.path.isabs(binary) or not os.path.isfile(binary)
+	    or not os.access(binary, os.X_OK)):
+		binary = path_lookup and find_binary(binary) or None
+		if not binary:
+			raise CommandNotFound(mycommand[0])
+
+	# If we haven't been told what file descriptors to use
+	# default to propogating our stdin, stdout and stderr.
+	if fd_pipes is None:
+		fd_pipes = {0:0, 1:1, 2:2}
+
+	# mypids will hold the pids of all processes created.
+	mypids = []
+
+	if logfile:
+		# Using a log file requires that stdout and stderr
+		# are assigned to the process we're running.
+		if 1 not in fd_pipes or 2 not in fd_pipes:
+			raise ValueError(fd_pipes)
+
+		# Create a pipe
+		(pr, pw) = os.pipe()
+
+		# Create a tee process, giving it our stdout and stderr
+		# as well as the read end of the pipe.
+		mypids.extend(spawn(('tee', '-i', '-a', logfile),
+		              returnpid=True, fd_pipes={0:pr,
+		              1:fd_pipes[1], 2:fd_pipes[2]}))
+
+		# We don't need the read end of the pipe, so close it.
+		os.close(pr)
+
+		# Assign the write end of the pipe to our stdout and stderr.
+		fd_pipes[1] = pw
+		fd_pipes[2] = pw
+
+	pid = os.fork()
+
+	if not pid:
+		try:
+			_exec(binary, mycommand, opt_name, fd_pipes,
+			      env, gid, groups, uid, umask)
+		except Exception, e:
+			# We need to catch _any_ exception so that it doesn't
+			# propogate out of this function and cause exiting
+			# with anything other than os._exit()
+			sys.stderr.write("%s:\n   %s\n" % (e, " ".join(mycommand)))
+			sys.stderr.flush()
+			os._exit(1)
+
+	# Add the pid to our local and the global pid lists.
+	mypids.append(pid)
+	spawned_pids.append(pid)
+
+	# If we started a tee process the write side of the pipe is no
+	# longer needed, so close it.
+	if logfile:
+		os.close(pw)
+
+	# If the caller wants to handle cleaning up the processes, we tell
+	# it about all processes that were created.
+	if returnpid:
+		return mypids
+
+	# Otherwise we clean them up.
+	while mypids:
+
+		# Pull the last reader in the pipe chain. If all processes
+		# in the pipe are well behaved, it will die when the process
+		# it is reading from dies.
+		pid = mypids.pop(0)
+
+		# and wait for it.
+		retval = os.waitpid(pid, 0)[1]
+
+		# When it's done, we can remove it from the
+		# global pid list as well.
+		spawned_pids.remove(pid)
+
+		if retval:
+			# If it failed, kill off anything else that
+			# isn't dead yet.
+			for pid in mypids:
+				if os.waitpid(pid, os.WNOHANG) == (0,0):
+					os.kill(pid, signal.SIGTERM)
+					os.waitpid(pid, 0)
+				spawned_pids.remove(pid)
+
+			# If it got a signal, return the signal that was sent.
+			if (retval & 0xff):
+				return ((retval & 0xff) << 8)
+
+			# Otherwise, return its exit code.
+			return (retval >> 8)
+
+	# Everything succeeded
+	return 0
+
+def _exec(binary, mycommand, opt_name, fd_pipes, env, gid, groups, uid, umask):
+
+	"""
+	Execute a given binary with options
+	
+	@param binary: Name of program to execute
+	@type binary: String
+	@param mycommand: Options for program
+	@type mycommand: String
+	@param opt_name: Name of process (defaults to binary)
+	@type opt_name: String
+	@param fd_pipes: Mapping pipes to destination; { 0:0, 1:1, 2:2 }
+	@type fd_pipes: Dictionary
+	@param env: Key,Value mapping for Environmental Variables
+	@type env: Dictionary
+	@param gid: Group ID to run the process under
+	@type gid: Integer
+	@param groups: Groups the Process should be in.
+	@type groups: Integer
+	@param uid: User ID to run the process under
+	@type uid: Integer
+	@param umask: an int representing a unix umask (see man chmod for umask details)
+	@type umask: Integer
+	@rtype: None
+	@returns: Never returns (calls os.execve)
+	"""
+	
+	# If the process we're creating hasn't been given a name
+	# assign it the name of the executable.
+	if not opt_name:
+		opt_name = os.path.basename(binary)
+
+	# Set up the command's argument list.
+	myargs = [opt_name]
+	myargs.extend(mycommand[1:])
+
+	# Set up the command's pipes.
+	my_fds = {}
+	# To protect from cases where direct assignment could
+	# clobber needed fds ({1:2, 2:1}) we first dupe the fds
+	# into unused fds.
+	for fd in fd_pipes:
+		my_fds[fd] = os.dup(fd_pipes[fd])
+	# Then assign them to what they should be.
+	for fd in my_fds:
+		os.dup2(my_fds[fd], fd)
+	# Then close _all_ fds that haven't been explictly
+	# requested to be kept open.
+	for fd in get_open_fds():
+		if fd not in my_fds:
+			try:
+				os.close(fd)
+			except OSError:
+				pass
+
+	# Set requested process permissions.
+	if gid:
+		os.setgid(gid)
+	if groups:
+		os.setgroups(groups)
+	if uid:
+		os.setuid(uid)
+	if umask:
+		os.umask(umask)
+
+	# And switch to the new process.
+	os.execve(binary, myargs, env)
+
+def find_binary(binary):
+	"""
+	Given a binary name, find the binary in PATH
+	
+	@param binary: Name of the binary to find
+	@type string
+	@rtype: None or string
+	@returns: full path to binary or None if the binary could not be located.
+	"""
+	
+	for path in os.getenv("PATH", "").split(":"):
+		filename = "%s/%s" % (path, binary)
+		if os.access(filename, os.X_OK) and os.path.isfile(filename):
+			return filename
+	return None
Index: /vendor/portage/current/pym/portage_gpg.py
===================================================================
--- /vendor/portage/current/pym/portage_gpg.py	(revision 3419)
+++ /vendor/portage/current/pym/portage_gpg.py	(revision 3419)
@@ -0,0 +1,149 @@
+# portage_gpg.py -- core Portage functionality
+# Copyright 2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: portage_gpg.py 3483 2006-06-10 21:40:40Z genone $
+
+
+import os
+import copy
+import types
+import commands
+import portage_exception
+import portage_checksum
+
+GPG_BINARY       = "/usr/bin/gpg"
+GPG_OPTIONS      = " --lock-never --no-random-seed-file --no-greeting --no-sig-cache "
+GPG_VERIFY_FLAGS = " --verify "
+GPG_KEYDIR       = " --homedir '%s' "
+GPG_KEYRING      = " --keyring '%s' "
+
+UNTRUSTED = 0
+EXISTS    = UNTRUSTED + 1
+MARGINAL  = EXISTS    + 1
+TRUSTED   = MARGINAL  + 1
+
+def fileStats(filepath):
+	mya = []
+	for x in os.stat(filepath):
+		mya.append(x)
+	mya.append(portage_checksum.perform_checksum(filepath))
+	return mya
+
+
+class FileChecker:
+	def __init__(self,keydir=None,keyring=None,requireSignedRing=False,minimumTrust=EXISTS):
+		self.minimumTrust     = TRUSTED  # Default we require trust. For rings.
+		self.keydir           = None
+		self.keyring          = None
+		self.keyringPath      = None
+		self.keyringStats     = None
+		self.keyringIsTrusted = False
+	
+		if (keydir != None):
+			# Verify that the keydir is valid.
+			if type(keydir) != types.StringType:
+				raise portage_exception.InvalidDataType, "keydir argument: %s" % keydir
+			if not os.path.isdir(keydir):
+				raise portage_exception.DirectoryNotFound, "keydir: %s" % keydir
+			self.keydir = copy.deepcopy(keydir)
+
+		if (keyring != None):
+			# Verify that the keyring is a valid filename and exists.
+			if type(keyring) != types.StringType:
+				raise portage_exception.InvalidDataType, "keyring argument: %s" % keyring
+			if keyring.find("/") != -1:
+				raise portage_exception.InvalidData, "keyring: %s" % keyring
+			pathname = ""
+			if keydir:
+				pathname = keydir + "/" + keyring
+			if not os.path.isfile(pathname):
+				raise portage_exception.FileNotFound, "keyring missing: %s (dev.gentoo.org/~carpaski/gpg/)" % pathname
+
+		keyringPath = keydir+"/"+keyring
+
+		if not keyring or not keyringPath and requireSignedRing:
+			raise portage_exception.MissingParameter
+
+		self.keyringStats = fileStats(keyringPath)
+		self.minimumTrust = TRUSTED
+		if not self.verify(keyringPath, keyringPath+".asc"):
+			self.keyringIsTrusted = False
+			if requireSignedRing:
+				raise portage_exception.InvalidSignature, "Required keyring verification: "+keyringPath
+		else:
+			self.keyringIsTrusted = True
+		
+		self.keyring      = copy.deepcopy(keyring)
+		self.keyringPath  = self.keydir+"/"+self.keyring
+		self.minimumTrust = minimumTrust
+
+	def _verifyKeyring(self):
+		if self.keyringStats and self.keyringPath:
+			new_stats = fileStats(self.keyringPath)
+			if new_stats != self.keyringStats:
+				raise portage_exception.SecurityViolation, "GPG keyring changed!"
+
+	def verify(self, filename, sigfile=None):
+		"""Uses minimumTrust to determine if it is Valid/True or Invalid/False"""
+		self._verifyKeyring()
+
+		if not os.path.isfile(filename):
+			raise portage_exception.FileNotFound, filename
+		
+		if sigfile and not os.path.isfile(sigfile):
+			raise portage_exception.FileNotFound, sigfile
+		
+		if self.keydir and not os.path.isdir(self.keydir):
+			raise portage_exception.DirectoryNotFound, filename
+		
+		if self.keyringPath:
+			if not os.path.isfile(self.keyringPath):
+				raise portage_exception.FileNotFound, self.keyringPath
+
+		if not os.path.isfile(filename):
+			raise portage_exception.CommandNotFound, filename
+
+		command = GPG_BINARY + GPG_VERIFY_FLAGS + GPG_OPTIONS
+		if self.keydir:
+			command += GPG_KEYDIR % (self.keydir)
+		if self.keyring:
+			command += GPG_KEYRING % (self.keyring)
+		
+		if sigfile:
+			command += " '"+sigfile+"'"
+		command += " '"+filename+"'"
+	
+		result,output = commands.getstatusoutput(command)
+		
+		signal = result & 0xff
+		result = (result >> 8)
+	
+		if signal:
+			raise SignalCaught, "Signal: %d" % (signal)
+	
+		trustLevel     = UNTRUSTED
+		if result == 0:
+			trustLevel   = TRUSTED
+			#if output.find("WARNING") != -1:
+			#	trustLevel = MARGINAL
+			if output.find("BAD") != -1:
+				raise portage_exception.InvalidSignature, filename
+		elif result == 1:
+			trustLevel   = EXISTS
+			if output.find("BAD") != -1:
+				raise portage_exception.InvalidSignature, filename
+		elif result == 2:
+			trustLevel   = UNTRUSTED
+			if output.find("could not be verified") != -1:
+				raise portage_exception.MissingSignature, filename
+			if output.find("public key not found") != -1:
+				if self.keyringIsTrusted: # We trust the ring, but not the key specifically.
+					trustLevel = MARGINAL
+				else:
+					raise portage_exception.InvalidSignature, filename+" (Unknown Signature)"
+		else:
+			raise portage_exception.UnknownCondition, "GPG returned unknown result: %d" % (result)
+	
+		if trustLevel >= self.minimumTrust:
+			return True
+		return False
Index: /vendor/portage/current/pym/portage_localization.py
===================================================================
--- /vendor/portage/current/pym/portage_localization.py	(revision 3419)
+++ /vendor/portage/current/pym/portage_localization.py	(revision 3419)
@@ -0,0 +1,21 @@
+# portage_localization.py -- Code to manage/help portage localization.
+# Copyright 2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: portage_localization.py 3483 2006-06-10 21:40:40Z genone $
+
+
+# We define this to make the transition easier for us.
+def _(mystr):
+	return mystr
+
+
+def localization_example():
+	# Dict references allow translators to rearrange word order.
+	print _("You can use this string for translating.")
+	print _("Strings can be formatted with %(mystr)s like this.") % {"mystr": "VALUES"}
+
+	a_value = "value.of.a"
+	b_value = 123
+	c_value = [1,2,3,4]
+	print _("A: %(a)s -- B: %(b)s -- C: %(c)s") % {"a":a_value,"b":b_value,"c":c_value}
+
Index: /vendor/portage/current/pym/portage_locks.py
===================================================================
--- /vendor/portage/current/pym/portage_locks.py	(revision 3419)
+++ /vendor/portage/current/pym/portage_locks.py	(revision 3419)
@@ -0,0 +1,323 @@
+# portage: Lock management code
+# Copyright 2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: portage_locks.py 5595 2007-01-12 08:08:03Z antarus $
+
+
+import errno
+import os
+import stat
+import time
+import types
+import portage_exception
+import portage_util
+import portage_data
+from portage_localization import _
+
+HARDLINK_FD = -2
+
+def lockdir(mydir):
+	return lockfile(mydir,wantnewlockfile=1)
+def unlockdir(mylock):
+	return unlockfile(mylock)
+
+def lockfile(mypath, wantnewlockfile=0, unlinkfile=0, waiting_msg=None):
+	"""Creates all dirs upto, the given dir. Creates a lockfile
+	for the given directory as the file: directoryname+'.portage_lockfile'."""
+	import fcntl
+
+	if not mypath:
+		raise portage_exception.InvalidData, "Empty path given"
+
+	if type(mypath) == types.StringType and mypath[-1] == '/':
+		mypath = mypath[:-1]
+
+	if type(mypath) == types.FileType:
+		mypath = mypath.fileno()
+	if type(mypath) == types.IntType:
+		lockfilename    = mypath
+		wantnewlockfile = 0
+		unlinkfile      = 0
+	elif wantnewlockfile:
+		base, tail = os.path.split(mypath)
+		lockfilename = os.path.join(base, "." + tail + ".portage_lockfile")
+		del base, tail
+		unlinkfile   = 1
+	else:
+		lockfilename = mypath
+	
+	if type(mypath) == types.StringType:
+		if not os.path.exists(os.path.dirname(mypath)):
+			raise portage_exception.DirectoryNotFound, os.path.dirname(mypath)
+		if not os.path.exists(lockfilename):
+			old_mask=os.umask(000)
+			myfd = os.open(lockfilename, os.O_CREAT|os.O_RDWR,0660)
+			try:
+				if os.stat(lockfilename).st_gid != portage_data.portage_gid:
+					os.chown(lockfilename,os.getuid(),portage_data.portage_gid)
+			except OSError, e:
+				if e[0] == 2: # No such file or directory
+					return lockfile(mypath, wantnewlockfile=wantnewlockfile,
+						unlinkfile=unlinkfile, waiting_msg=waiting_msg)
+				else:
+					portage_util.writemsg("Cannot chown a lockfile. This could cause inconvenience later.\n");
+			os.umask(old_mask)
+		else:
+			myfd = os.open(lockfilename, os.O_CREAT|os.O_RDWR,0660)
+
+	elif type(mypath) == types.IntType:
+		myfd = mypath
+
+	else:
+		raise ValueError, "Unknown type passed in '%s': '%s'" % (type(mypath),mypath)
+
+	# try for a non-blocking lock, if it's held, throw a message
+	# we're waiting on lockfile and use a blocking attempt.
+	locking_method = fcntl.lockf
+	try:
+		fcntl.lockf(myfd,fcntl.LOCK_EX|fcntl.LOCK_NB)
+	except IOError, e:
+		if "errno" not in dir(e):
+			raise
+		if e.errno == errno.EAGAIN:
+			# resource temp unavailable; eg, someone beat us to the lock.
+			if waiting_msg is None:
+				if isinstance(mypath, int):
+					print "waiting for lock on fd %i" % myfd
+				else:
+					print "waiting for lock on %s" % lockfilename
+			elif waiting_msg:
+				print waiting_msg
+			# try for the exclusive lock now.
+			fcntl.lockf(myfd,fcntl.LOCK_EX)
+		elif e.errno == errno.ENOLCK:
+			# We're not allowed to lock on this FS.
+			os.close(myfd)
+			link_success = False
+			if lockfilename == str(lockfilename):
+				if wantnewlockfile:
+					try:
+						if os.stat(lockfilename)[stat.ST_NLINK] == 1:
+							os.unlink(lockfilename)
+					except OSError:
+						pass
+					link_success = hardlink_lockfile(lockfilename)
+			if not link_success:
+				raise
+			locking_method = None
+			myfd = HARDLINK_FD
+		else:
+			raise
+
+		
+	if type(lockfilename) == types.StringType and \
+		myfd != HARDLINK_FD and os.fstat(myfd).st_nlink == 0:
+		# The file was deleted on us... Keep trying to make one...
+		os.close(myfd)
+		portage_util.writemsg("lockfile recurse\n",1)
+		lockfilename, myfd, unlinkfile, locking_method = lockfile(
+			mypath, wantnewlockfile=wantnewlockfile, unlinkfile=unlinkfile,
+			waiting_msg=waiting_msg)
+
+	portage_util.writemsg(str((lockfilename,myfd,unlinkfile))+"\n",1)
+	return (lockfilename,myfd,unlinkfile,locking_method)
+
+def unlockfile(mytuple):
+	import fcntl
+
+	#XXX: Compatability hack.
+	if len(mytuple) == 3:
+		lockfilename,myfd,unlinkfile = mytuple
+		locking_method = fcntl.flock
+	elif len(mytuple) == 4:
+		lockfilename,myfd,unlinkfile,locking_method = mytuple
+	else:
+		raise
+
+	if(myfd == HARDLINK_FD):
+		unhardlink_lockfile(lockfilename)
+		return True
+	
+	# myfd may be None here due to myfd = mypath in lockfile()
+	if type(lockfilename) == types.StringType and not os.path.exists(lockfilename):
+		portage_util.writemsg("lockfile does not exist '%s'\n" % lockfilename,1)
+		if myfd is not None:
+			os.close(myfd)
+		return False
+
+	try:
+		if myfd is None:
+			myfd = os.open(lockfilename, os.O_WRONLY,0660)
+			unlinkfile = 1
+		locking_method(myfd,fcntl.LOCK_UN)
+	except OSError:
+		if type(lockfilename) == types.StringType:
+			os.close(myfd)
+		raise IOError, "Failed to unlock file '%s'\n" % lockfilename
+
+	try:
+		# This sleep call was added to allow other processes that are
+		# waiting for a lock to be able to grab it before it is deleted.
+		# lockfile() already accounts for this situation, however, and
+		# the sleep here adds more time than is saved overall, so am
+		# commenting until it is proved necessary.
+		#time.sleep(0.0001)
+		if unlinkfile:
+			locking_method(myfd,fcntl.LOCK_EX|fcntl.LOCK_NB)
+			# We won the lock, so there isn't competition for it.
+			# We can safely delete the file.
+			portage_util.writemsg("Got the lockfile...\n",1)
+			if os.fstat(myfd).st_nlink == 1:
+				os.unlink(lockfilename)
+				portage_util.writemsg("Unlinked lockfile...\n",1)
+				locking_method(myfd,fcntl.LOCK_UN)
+			else:
+				portage_util.writemsg("lockfile does not exist '%s'\n" % lockfilename,1)
+				os.close(myfd)
+				return False
+	except Exception, e:
+		portage_util.writemsg("Failed to get lock... someone took it.\n",1)
+		portage_util.writemsg(str(e)+"\n",1)
+
+	# why test lockfilename?  because we may have been handed an
+	# fd originally, and the caller might not like having their
+	# open fd closed automatically on them.
+	if type(lockfilename) == types.StringType:
+		os.close(myfd)
+
+	return True
+
+
+
+
+def hardlock_name(path):
+	return path+".hardlock-"+os.uname()[1]+"-"+str(os.getpid())
+
+def hardlink_is_mine(link,lock):
+	try:
+		return os.stat(link).st_nlink == 2
+	except OSError:
+		return False
+
+def hardlink_lockfile(lockfilename, max_wait=14400):
+	"""Does the NFS, hardlink shuffle to ensure locking on the disk.
+	We create a PRIVATE lockfile, that is just a placeholder on the disk.
+	Then we HARDLINK the real lockfile to that private file.
+	If our file can 2 references, then we have the lock. :)
+	Otherwise we lather, rise, and repeat.
+	We default to a 4 hour timeout.
+	"""
+
+	start_time = time.time()
+	myhardlock = hardlock_name(lockfilename)
+	reported_waiting = False
+	
+	while(time.time() < (start_time + max_wait)):
+		# We only need it to exist.
+		myfd = os.open(myhardlock, os.O_CREAT|os.O_RDWR,0660)
+		os.close(myfd)
+	
+		if not os.path.exists(myhardlock):
+			raise portage_exception.FileNotFound, _("Created lockfile is missing: %(filename)s") % {"filename":myhardlock}
+
+		try:
+			res = os.link(myhardlock, lockfilename)
+		except OSError:
+			pass
+
+		if hardlink_is_mine(myhardlock, lockfilename):
+			# We have the lock.
+			if reported_waiting:
+				print
+			return True
+
+		if reported_waiting:
+			portage_util.writemsg(".")
+		else:
+			reported_waiting = True
+			from portage_const import PORTAGE_BIN_PATH
+			print
+			print "Waiting on (hardlink) lockfile: (one '.' per 3 seconds)"
+			print "This is a feature to prevent distfiles corruption."
+			print "%s/clean_locks can fix stuck locks." % PORTAGE_BIN_PATH
+			print "Lockfile: " + lockfilename
+		time.sleep(3)
+	
+	os.unlink(myhardlock)
+	return False
+
+def unhardlink_lockfile(lockfilename):
+	myhardlock = hardlock_name(lockfilename)
+	if hardlink_is_mine(myhardlock, lockfilename):
+		# Make sure not to touch lockfilename unless we really have a lock.
+		try:
+			os.unlink(lockfilename)
+		except OSError:
+			pass
+	try:
+		os.unlink(myhardlock)
+	except OSError:
+		pass
+
+def hardlock_cleanup(path, remove_all_locks=False):
+	mypid  = str(os.getpid())
+	myhost = os.uname()[1]
+	mydl = os.listdir(path)
+
+	results = []
+	mycount = 0
+
+	mylist = {}
+	for x in mydl:
+		if os.path.isfile(path+"/"+x):
+			parts = x.split(".hardlock-")
+			if len(parts) == 2:
+				filename = parts[0]
+				hostpid  = parts[1].split("-")
+				host  = "-".join(hostpid[:-1])
+				pid   = hostpid[-1]
+				
+				if not mylist.has_key(filename):
+					mylist[filename] = {}
+				if not mylist[filename].has_key(host):
+					mylist[filename][host] = []
+				mylist[filename][host].append(pid)
+
+				mycount += 1
+
+
+	results.append("Found %(count)s locks" % {"count":mycount})
+	
+	for x in mylist.keys():
+		if mylist[x].has_key(myhost) or remove_all_locks:
+			mylockname = hardlock_name(path+"/"+x)
+			if hardlink_is_mine(mylockname, path+"/"+x) or \
+			   not os.path.exists(path+"/"+x) or \
+				 remove_all_locks:
+				for y in mylist[x].keys():
+					for z in mylist[x][y]:
+						filename = path+"/"+x+".hardlock-"+y+"-"+z
+						if filename == mylockname:
+							continue
+						try:
+							# We're sweeping through, unlinking everyone's locks.
+							os.unlink(filename)
+							results.append(_("Unlinked: ") + filename)
+						except OSError:
+							pass
+				try:
+					os.unlink(path+"/"+x)
+					results.append(_("Unlinked: ") + path+"/"+x)
+					os.unlink(mylockname)
+					results.append(_("Unlinked: ") + mylockname)
+				except OSError:
+					pass
+			else:
+				try:
+					os.unlink(mylockname)
+					results.append(_("Unlinked: ") + mylockname)
+				except OSError:
+					pass
+
+	return results
+
Index: /vendor/portage/current/pym/portage_mail.py
===================================================================
--- /vendor/portage/current/pym/portage_mail.py	(revision 3419)
+++ /vendor/portage/current/pym/portage_mail.py	(revision 3419)
@@ -0,0 +1,89 @@
+# portage.py -- core Portage functionality
+# Copyright 1998-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: portage.py 3483 2006-06-10 21:40:40Z genone $
+
+import portage_exception, socket, smtplib, os, sys, time
+from email.MIMEText import MIMEText as TextMessage
+from email.MIMEMultipart import MIMEMultipart as MultipartMessage
+from email.MIMEBase import MIMEBase as BaseMessage
+
+def create_message(sender, recipient, subject, body, attachments=None):
+	if attachments == None:
+		mymessage = TextMessage(body)
+	else:
+		mymessage = MultipartMessage()
+		mymessage.attach(TextMessage(body))
+		for x in attachments:
+			if isinstance(x, BaseMessage):
+				mymessage.attach(x)
+			elif isinstance(x, str):
+				mymessage.attach(TextMessage(x))
+			else:
+				raise portage_exception.PortageException("Can't handle type of attachment: %s" % type(x))
+
+	mymessage.set_unixfrom(sender)
+	mymessage["To"] = recipient
+	mymessage["From"] = sender
+	mymessage["Subject"] = subject
+	mymessage["Date"] = time.strftime("%a, %d %b %Y %H:%M:%S %z")
+	
+	return mymessage
+
+def send_mail(mysettings, message):
+	mymailhost = "localhost"
+	mymailport = 25
+	mymailuser = ""
+	mymailpasswd = ""
+	myrecipient = "root@localhost"
+	
+	# Syntax for PORTAGE_ELOG_MAILURI (if defined):
+	# adress [[user:passwd@]mailserver[:port]]
+	# where adress:     recipient adress
+	#       user:       username for smtp auth (defaults to none)
+	#       passwd:     password for smtp auth (defaults to none)
+	#       mailserver: smtp server that should be used to deliver the mail (defaults to localhost)
+	#					alternatively this can also be the absolute path to a sendmail binary if you don't want to use smtp
+	#       port:       port to use on the given smtp server (defaults to 25, values > 100000 indicate that starttls should be used on (port-100000))
+	if " " in mysettings["PORTAGE_ELOG_MAILURI"]:
+		myrecipient, mymailuri = mysettings["PORTAGE_ELOG_MAILURI"].split()
+		if "@" in mymailuri:
+			myauthdata, myconndata = mymailuri.rsplit("@", 1)
+			try:
+				mymailuser,mymailpasswd = myauthdata.split(":")
+			except ValueError:
+				print "!!! invalid SMTP AUTH configuration, trying unauthenticated ..."
+		else:
+			myconndata = mymailuri
+		if ":" in myconndata:
+			mymailhost,mymailport = myconndata.split(":")
+		else:
+			mymailhost = myconndata
+	else:
+		myrecipient = mysettings["PORTAGE_ELOG_MAILURI"]
+	
+	myfrom = message.get("From")
+		
+	# user wants to use a sendmail binary instead of smtp
+	if mymailhost[0] == os.sep and os.path.exists(mymailhost):
+		fd = os.popen(mymailhost+" -f "+myfrom+" "+myrecipient, "w")
+		fd.write(message.as_string())
+		if fd.close() != None:
+			sys.stderr.write("!!! %s returned with a non-zero exit code. This generally indicates an error.\n" % mymailhost)
+	else:
+		try:
+			if int(mymailport) > 100000:
+				myconn = smtplib.SMTP(mymailhost, int(mymailport) - 100000)
+				myconn.starttls()
+			else:
+				myconn = smtplib.SMTP(mymailhost, mymailport)
+			if mymailuser != "" and mymailpasswd != "":
+				myconn.login(mymailuser, mymailpasswd)
+			myconn.sendmail(myfrom, myrecipient, message.as_string())
+			myconn.quit()
+		except smtplib.SMTPException, e:
+			raise portage_exception.PortageException("!!! An error occured while trying to send logmail:\n"+str(e))
+		except socket.error, e:
+			raise portage_exception.PortageException("!!! A network error occured while trying to send logmail:\n"+str(e)+"\nSure you configured PORTAGE_ELOG_MAILURI correctly?")
+	return
+	
Index: /vendor/portage/current/pym/portage_manifest.py
===================================================================
--- /vendor/portage/current/pym/portage_manifest.py	(revision 3419)
+++ /vendor/portage/current/pym/portage_manifest.py	(revision 3419)
@@ -0,0 +1,618 @@
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+import errno, os, sets
+if not hasattr(__builtins__, "set"):
+	from sets import Set as set
+
+import portage_exception, portage_versions, portage_const
+from portage_checksum import *
+from portage_exception import *
+from portage_util import write_atomic
+
+class FileNotInManifestException(PortageException):
+	pass
+
+def manifest2AuxfileFilter(filename):
+	filename = filename.strip(os.sep)
+	mysplit = filename.split(os.path.sep)
+	if "CVS" in mysplit:
+		return False
+	for x in mysplit:
+		if x.startswith("."):
+			return False
+	return not filename.startswith("digest-")
+
+def manifest2MiscfileFilter(filename):
+	filename = filename.strip(os.sep)
+	return not (filename in ["CVS", ".svn", "files", "Manifest"] or filename.endswith(".ebuild"))
+
+def guessManifestFileType(filename):
+	""" Perform a best effort guess of which type the given filename is, avoid using this if possible """
+	if filename.startswith("files" + os.sep + "digest-"):
+		return None
+	if filename.startswith("files" + os.sep):
+		return "AUX"
+	elif filename.endswith(".ebuild"):
+		return "EBUILD"
+	elif filename in ["ChangeLog", "metadata.xml"]:
+		return "MISC"
+	else:
+		return "DIST"
+
+def parseManifest2(mysplit):
+	myentry = None
+	if len(mysplit) > 4 and mysplit[0] in portage_const.MANIFEST2_IDENTIFIERS:
+		mytype = mysplit[0]
+		myname = mysplit[1]
+		mysize = int(mysplit[2])
+		myhashes = dict(zip(mysplit[3::2], mysplit[4::2]))
+		myhashes["size"] = mysize
+		myentry = Manifest2Entry(type=mytype, name=myname, hashes=myhashes)
+	return myentry
+
+def parseManifest1(mysplit):
+	myentry = None
+	if len(mysplit) == 4 and mysplit[0] in ["size"] + portage_const.MANIFEST1_HASH_FUNCTIONS:
+		myname = mysplit[2]
+		mytype = None
+		mytype = guessManifestFileType(myname)
+		if mytype == "AUX":
+			if myname.startswith("files" + os.path.sep):
+				myname = myname[6:]
+		mysize = int(mysplit[3])
+		myhashes = {mysplit[0]: mysplit[1]}
+		myhashes["size"] = mysize
+		myentry = Manifest1Entry(type=mytype, name=myname, hashes=myhashes)
+	return myentry
+
+class ManifestEntry(object):
+	__slots__ = ("type", "name", "hashes")
+	def __init__(self, **kwargs):
+		for k, v in kwargs.iteritems():
+			setattr(self, k, v)
+	def __cmp__(self, other):
+		if str(self) == str(other):
+			return 0
+		return 1
+
+class Manifest1Entry(ManifestEntry):
+	def __str__(self):
+		myhashkeys = self.hashes.keys()
+		for hashkey in myhashkeys:
+			if hashkey != "size":
+				break
+		hashvalue = self.hashes[hashkey]
+		myname = self.name
+		if self.type == "AUX" and not myname.startswith("files" + os.sep):
+			myname = os.path.join("files", myname)
+		return " ".join([hashkey, str(hashvalue), myname, str(self.hashes["size"])])
+
+class Manifest2Entry(ManifestEntry):
+	def __str__(self):
+		myline = " ".join([self.type, self.name, str(self.hashes["size"])])
+		myhashkeys = self.hashes.keys()
+		myhashkeys.remove("size")
+		myhashkeys.sort()
+		for h in myhashkeys:
+			myline += " " + h + " " + str(self.hashes[h])
+		return myline
+
+class Manifest(object):
+	parsers = (parseManifest2, parseManifest1)
+	def __init__(self, pkgdir, distdir, fetchlist_dict=None,
+		manifest1_compat=True, from_scratch=False):
+		""" create new Manifest instance for package in pkgdir
+		    and add compability entries for old portage versions if manifest1_compat == True.
+		    Do not parse Manifest file if from_scratch == True (only for internal use)
+			The fetchlist_dict parameter is required only for generation of
+			a Manifest (not needed for parsing and checking sums)."""
+		self.pkgdir = pkgdir.rstrip(os.sep) + os.sep
+		self.fhashdict = {}
+		self.hashes = portage_const.MANIFEST2_HASH_FUNCTIONS[:]
+		self.hashes.append("size")
+		if manifest1_compat:
+			self.hashes.extend(portage_const.MANIFEST1_HASH_FUNCTIONS)
+		self.hashes = sets.Set(self.hashes)
+		for t in portage_const.MANIFEST2_IDENTIFIERS:
+			self.fhashdict[t] = {}
+		self.compat = manifest1_compat
+		if not from_scratch:
+			self._read()
+		self.fetchlist_dict = fetchlist_dict
+		self.distdir = distdir
+		self.guessType = guessManifestFileType
+
+	def getFullname(self):
+		""" Returns the absolute path to the Manifest file for this instance """
+		return os.path.join(self.pkgdir, "Manifest")
+	
+	def getDigests(self):
+		""" Compability function for old digest/manifest code, returns dict of filename:{hashfunction:hashvalue} """
+		rval = {}
+		for t in portage_const.MANIFEST2_IDENTIFIERS:
+			rval.update(self.fhashdict[t])
+		return rval
+	
+	def getTypeDigests(self, ftype):
+		""" Similar to getDigests(), but restricted to files of the given type. """
+		return self.fhashdict[ftype]
+
+	def _readDigests(self, myhashdict=None):
+		""" Parse old style digest files for this Manifest instance """
+		if myhashdict is None:
+			myhashdict = {}
+		try:
+			for d in os.listdir(os.path.join(self.pkgdir, "files")):
+				if d.startswith("digest-"):
+					self._readManifest(os.path.join(self.pkgdir, "files", d), mytype="DIST",
+						myhashdict=myhashdict)
+		except (IOError, OSError), e:
+			if e.errno == errno.ENOENT:
+				pass
+			else:
+				raise
+		return myhashdict
+
+	def _readManifest(self, file_path, myhashdict=None, **kwargs):
+		"""Parse a manifest or an old style digest.  If myhashdict is given
+		then data will be added too it.  Otherwise, a new dict will be created
+		and returned."""
+		try:
+			fd = open(file_path, "r")
+			if myhashdict is None:
+				myhashdict = {}
+			self._parseDigests(fd, myhashdict=myhashdict, **kwargs)
+			fd.close()
+			return myhashdict
+		except (OSError, IOError), e:
+			if e.errno == errno.ENOENT:
+				raise FileNotFound(file_path)
+			else:
+				raise
+
+	def _read(self):
+		""" Parse Manifest file for this instance """
+		try:
+			self._readManifest(self.getFullname(), myhashdict=self.fhashdict)
+		except FileNotFound:
+			pass
+		if self.compat:
+			self._readDigests(myhashdict=self.fhashdict)
+
+	def _parseManifestLines(self, mylines):
+		"""Parse manifest lines and return a list of manifest entries."""
+		for myline in mylines:
+			myentry = None
+			mysplit = myline.split()
+			for parser in self.parsers:
+				myentry = parser(mysplit)
+				if myentry is not None:
+					yield myentry
+					break # go to the next line
+
+	def _parseDigests(self, mylines, myhashdict=None, mytype=None):
+		"""Parse manifest entries and store the data in myhashdict.  If mytype
+		is specified, it will override the type for all parsed entries."""
+		if myhashdict is None:
+			myhashdict = {}
+		for myentry in self._parseManifestLines(mylines):
+			if mytype is None:
+				myentry_type = myentry.type
+			else:
+				myentry_type = mytype
+			myhashdict.setdefault(myentry_type, {})
+			myhashdict[myentry_type].setdefault(myentry.name, {})
+			myhashdict[myentry_type][myentry.name].update(myentry.hashes)
+		return myhashdict
+
+	def _writeDigests(self, force=False):
+		""" Create old style digest files for this Manifest instance """
+		cpvlist = [os.path.join(self._pkgdir_category(), x[:-7]) for x in os.listdir(self.pkgdir) if x.endswith(".ebuild")]
+		rval = []
+		try:
+			os.makedirs(os.path.join(self.pkgdir, "files"))
+		except OSError, oe:
+			if oe.errno == errno.EEXIST:
+				pass
+			else:
+				raise
+		for cpv in cpvlist:
+			dname = os.path.join(self.pkgdir, "files", "digest-%s" % self._catsplit(cpv)[1])
+			distlist = self._getCpvDistfiles(cpv)
+			missing_digests = set()
+			for f in distlist:
+				if f not in self.fhashdict["DIST"] or len(self.fhashdict["DIST"][f]) == 0:
+					missing_digests.add(f)
+			if missing_digests:
+				# This allows us to force remove of stale digests for the
+				# ebuild --force digest option.
+				distlist = [f for f in distlist if f not in missing_digests]
+			update_digest = True
+			if not force:
+				try:
+					f = open(dname, "r")
+					old_data = self._parseDigests(f)
+					f.close()
+					if len(old_data) == 1 and "DIST" in old_data:
+						new_data = self._getDigestData(distlist)
+						if "DIST" in new_data:
+							for myfile in new_data["DIST"]:
+								for hashname in \
+									new_data["DIST"][myfile].keys():
+									if hashname != "size" and hashname not in \
+										portage_const.MANIFEST1_HASH_FUNCTIONS:
+										del new_data["DIST"][myfile][hashname]
+							if new_data["DIST"] == old_data["DIST"]:
+								update_digest = False
+				except (IOError, OSError), e:
+					if errno.ENOENT == e.errno:
+						pass
+					else:
+						raise
+			if update_digest:
+				mylines = self._createDigestLines1(distlist, self.fhashdict)
+				if mylines:
+					mylines = "\n".join(mylines) + "\n"
+				else:
+					mylines = ""
+				write_atomic(dname, mylines)
+			rval.append(dname)
+		return rval
+
+	def _getDigestData(self, distlist):
+		"""create a hash dict for a specific list of files"""
+		myhashdict = {}
+		for myname in distlist:
+			for mytype in self.fhashdict:
+				if myname in self.fhashdict[mytype]:
+					myhashdict.setdefault(mytype, {})
+					myhashdict[mytype].setdefault(myname, {})
+					myhashdict[mytype][myname].update(self.fhashdict[mytype][myname])
+		return myhashdict
+
+	def _createDigestLines1(self, distlist, myhashdict):
+		""" Create an old style digest file."""
+		mylines = []
+		myfiles = myhashdict["DIST"].keys()
+		myfiles.sort()
+		for f in myfiles:
+			if f in distlist:
+				myhashkeys = myhashdict["DIST"][f].keys()
+				myhashkeys.sort()
+				for h in myhashkeys:
+					if h not in portage_const.MANIFEST1_HASH_FUNCTIONS:
+						continue
+					myline = " ".join([h, str(myhashdict["DIST"][f][h]), f, str(myhashdict["DIST"][f]["size"])])
+					mylines.append(myline)
+		return mylines
+	
+	def _addDigestsToManifest(self, digests, fd):
+		""" Add entries for old style digest files to Manifest file """
+		mylines = []
+		for dname in digests:
+			myhashes = perform_multiple_checksums(dname, portage_const.MANIFEST1_HASH_FUNCTIONS+["size"])
+			for h in myhashes:
+				mylines.append((" ".join([h, str(myhashes[h]), os.path.join("files", os.path.basename(dname)), str(myhashes["size"])])))
+		fd.write("\n".join(mylines))
+		fd.write("\n")
+
+	def _createManifestEntries(self):
+		mytypes = self.fhashdict.keys()
+		mytypes.sort()
+		for t in mytypes:
+			myfiles = self.fhashdict[t].keys()
+			myfiles.sort()
+			for f in myfiles:
+				myentry = Manifest2Entry(
+					type=t, name=f, hashes=self.fhashdict[t][f].copy())
+				myhashkeys = myentry.hashes.keys()
+				for h in myhashkeys:
+					if h not in ["size"] + portage_const.MANIFEST2_HASH_FUNCTIONS:
+						del myentry.hashes[h]
+				yield myentry
+				if self.compat and t != "DIST":
+					mysize = self.fhashdict[t][f]["size"]
+					myhashes = self.fhashdict[t][f]
+					for h in myhashkeys:
+						if h not in portage_const.MANIFEST1_HASH_FUNCTIONS:
+							continue
+						yield Manifest1Entry(
+							type=t, name=f, hashes={"size":mysize, h:myhashes[h]})
+
+		if self.compat:
+			cvp_list = self.fetchlist_dict.keys()
+			cvp_list.sort()
+			for cpv in cvp_list:
+				digest_path = os.path.join("files", "digest-%s" % self._catsplit(cpv)[1])
+				dname = os.path.join(self.pkgdir, digest_path)
+				try:
+					myhashes = perform_multiple_checksums(dname, portage_const.MANIFEST1_HASH_FUNCTIONS+["size"])
+					myhashkeys = myhashes.keys()
+					myhashkeys.sort()
+					for h in myhashkeys:
+						if h in portage_const.MANIFEST1_HASH_FUNCTIONS:
+							yield Manifest1Entry(type="AUX", name=digest_path,
+								hashes={"size":myhashes["size"], h:myhashes[h]})
+				except FileNotFound:
+					pass
+
+	def write(self, sign=False, force=False):
+		""" Write Manifest instance to disk, optionally signing it """
+		try:
+			if self.compat:
+				self._writeDigests()
+			myentries = list(self._createManifestEntries())
+			update_manifest = True
+			if not force:
+				try:
+					f = open(self.getFullname(), "r")
+					oldentries = list(self._parseManifestLines(f))
+					f.close()
+					if len(oldentries) == len(myentries):
+						update_manifest = False
+						for i in xrange(len(oldentries)):
+							if oldentries[i] != myentries[i]:
+								update_manifest = True
+								break
+				except (IOError, OSError), e:
+					if e.errno == errno.ENOENT:
+						pass
+					else:
+						raise
+			if update_manifest:
+				fd = open(self.getFullname(), "w")
+				for myentry in myentries:
+					fd.write("%s\n" % str(myentry))
+				fd.close()
+			if sign:
+				self.sign()
+		except (IOError, OSError), e:
+			if e.errno == errno.EACCES:
+				raise PermissionDenied(str(e))
+			raise
+
+	def sign(self):
+		""" Sign the Manifest """
+		raise NotImplementedError()
+	
+	def validateSignature(self):
+		""" Validate signature on Manifest """
+		raise NotImplementedError()
+	
+	def addFile(self, ftype, fname, hashdict=None):
+		""" Add entry to Manifest optionally using hashdict to avoid recalculation of hashes """
+		if not os.path.exists(self.pkgdir+fname):
+			raise FileNotFound(fname)
+		if not ftype in portage_const.MANIFEST2_IDENTIFIERS:
+			raise InvalidDataType(ftype)
+		self.fhashdict[ftype][fname] = {}
+		if hashdict != None:
+			self.fhashdict[ftype][fname].update(hashdict)
+		if not portage_const.MANIFEST2_REQUIRED_HASH in self.fhashdict[ftype][fname]:
+			self.updateFileHashes(ftype, fname)
+	
+	def removeFile(self, ftype, fname):
+		""" Remove given entry from Manifest """
+		del self.fhashdict[ftype][fname]
+	
+	def hasFile(self, ftype, fname):
+		""" Return wether the Manifest contains an entry for the given type,filename pair """
+		return (fname in self.fhashdict[ftype])
+	
+	def findFile(self, fname):
+		""" Return entrytype of the given file if present in Manifest or None if not present """
+		for t in portage_const.MANIFEST2_IDENTIFIERS:
+			if fname in self.fhashdict[t]:
+				return t
+		return None
+	
+	def create(self, checkExisting=False, assumeDistHashesSometimes=False,
+		assumeDistHashesAlways=False, requiredDistfiles=[]):
+		""" Recreate this Manifest from scratch.  This will not use any
+		existing checksums unless assumeDistHashesSometimes or
+		assumeDistHashesAlways is true (assumeDistHashesSometimes will only
+		cause DIST checksums to be reused if the file doesn't exist in
+		DISTDIR).  The requiredDistfiles parameter specifies a list of
+		distfiles to raise a FileNotFound exception for (if no file or existing
+		checksums are available), and defaults to all distfiles when not
+		specified."""
+		if checkExisting:
+			self.checkAllHashes()
+		if assumeDistHashesSometimes or assumeDistHashesAlways:
+			distfilehashes = self.fhashdict["DIST"]
+		else:
+			distfilehashes = {}
+		self.__init__(self.pkgdir, self.distdir,
+			fetchlist_dict=self.fetchlist_dict, from_scratch=True,
+			manifest1_compat=self.compat)
+		for pkgdir, pkgdir_dirs, pkgdir_files in os.walk(self.pkgdir):
+			break
+		for f in pkgdir_files:
+			if f.endswith(".ebuild"):
+				mytype = "EBUILD"
+			elif manifest2MiscfileFilter(f):
+				mytype = "MISC"
+			else:
+				continue
+			self.fhashdict[mytype][f] = perform_multiple_checksums(self.pkgdir+f, self.hashes)
+		recursive_files = []
+		cut_len = len(os.path.join(self.pkgdir, "files") + os.sep)
+		for parentdir, dirs, files in os.walk(os.path.join(self.pkgdir, "files")):
+			for f in files:
+				full_path = os.path.join(parentdir, f)
+				recursive_files.append(full_path[cut_len:])
+		for f in recursive_files:
+			if not manifest2AuxfileFilter(f):
+				continue
+			self.fhashdict["AUX"][f] = perform_multiple_checksums(
+				os.path.join(self.pkgdir, "files", f.lstrip(os.sep)), self.hashes)
+		cpvlist = [os.path.join(self._pkgdir_category(), x[:-7]) for x in os.listdir(self.pkgdir) if x.endswith(".ebuild")]
+		distlist = set()
+		for cpv in cpvlist:
+			distlist.update(self._getCpvDistfiles(cpv))
+		if requiredDistfiles is None:
+			# This allows us to force removal of stale digests for the
+			# ebuild --force digest option (no distfiles are required).
+			requiredDistfiles = set()
+		elif len(requiredDistfiles) == 0:
+			# repoman passes in an empty list, which implies that all distfiles
+			# are required.
+			requiredDistfiles = distlist.copy()
+		required_hash_types = set()
+		required_hash_types.add("size")
+		required_hash_types.add(portage_const.MANIFEST2_REQUIRED_HASH)
+		
+		for f in distlist:
+			fname = os.path.join(self.distdir, f)
+			mystat = None
+			try:
+				mystat = os.stat(fname)
+			except OSError:
+				pass
+			if f in distfilehashes and \
+				((assumeDistHashesSometimes and mystat is None) or \
+				(assumeDistHashesAlways and mystat is None) or \
+				(assumeDistHashesAlways and mystat is not None and \
+				len(distfilehashes[f]) == len(self.hashes) and \
+				distfilehashes[f]["size"] == mystat.st_size)) and \
+				not required_hash_types.difference(distfilehashes[f]):
+				self.fhashdict["DIST"][f] = distfilehashes[f]
+			else:
+				try:
+					self.fhashdict["DIST"][f] = perform_multiple_checksums(fname, self.hashes)
+				except FileNotFound:
+					if f in requiredDistfiles:
+						raise
+
+	def _pkgdir_category(self):
+		return self.pkgdir.rstrip(os.sep).split(os.sep)[-2]
+
+	def _getAbsname(self, ftype, fname):
+		if ftype == "DIST":
+			absname = os.path.join(self.distdir, fname)
+		elif ftype == "AUX":
+			absname = os.path.join(self.pkgdir, "files", fname)
+		else:
+			absname = os.path.join(self.pkgdir, fname)
+		return absname	
+	
+	def checkAllHashes(self, ignoreMissingFiles=False):
+		for t in portage_const.MANIFEST2_IDENTIFIERS:
+			self.checkTypeHashes(t, ignoreMissingFiles=ignoreMissingFiles)
+	
+	def checkTypeHashes(self, idtype, ignoreMissingFiles=False):
+		for f in self.fhashdict[idtype]:
+			self.checkFileHashes(idtype, f, ignoreMissing=ignoreMissingFiles)
+	
+	def checkFileHashes(self, ftype, fname, ignoreMissing=False):
+		myhashes = self.fhashdict[ftype][fname]
+		try:
+			ok,reason = verify_all(self._getAbsname(ftype, fname), self.fhashdict[ftype][fname])
+			if not ok:
+				raise DigestException(tuple([self._getAbsname(ftype, fname)]+list(reason)))
+			return ok, reason
+		except FileNotFound, e:
+			if not ignoreMissing:
+				raise
+			return False, "File Not Found: '%s'" % str(e)
+
+	def checkCpvHashes(self, cpv, checkDistfiles=True, onlyDistfiles=False, checkMiscfiles=False):
+		""" check the hashes for all files associated to the given cpv, include all
+		AUX files and optionally all MISC files. """
+		if not onlyDistfiles:
+			self.checkTypeHashes("AUX", ignoreMissingFiles=False)
+			if checkMiscfiles:
+				self.checkTypeHashes("MISC", ignoreMissingFiles=False)
+			ebuildname = "%s.ebuild" % self._catsplit(cpv)[1]
+			self.checkFileHashes("EBUILD", ebuildname, ignoreMissing=False)
+		if checkDistfiles:
+			if onlyDistfiles:
+				for f in self._getCpvDistfiles(cpv):
+					self.checkFileHashes("DIST", f, ignoreMissing=False)
+	
+	def _getCpvDistfiles(self, cpv):
+		""" Get a list of all DIST files associated to the given cpv """
+		return self.fetchlist_dict[cpv]
+
+	def getDistfilesSize(self, fetchlist):
+		total_bytes = 0
+		for f in fetchlist:
+			total_bytes += int(self.fhashdict["DIST"][f]["size"])
+		return total_bytes
+
+	def updateFileHashes(self, ftype, fname, checkExisting=True, ignoreMissing=True, reuseExisting=False):
+		""" Regenerate hashes for the given file """
+		if checkExisting:
+			self.checkFileHashes(ftype, fname, ignoreMissing=ignoreMissing)
+		if not ignoreMissing and not self.fhashdict[ftype].has_key(fname):
+			raise FileNotInManifestException(fname)
+		if not self.fhashdict[ftype].has_key(fname):
+			self.fhashdict[ftype][fname] = {}
+		myhashkeys = list(self.hashes)
+		if reuseExisting:
+			for k in [h for h in self.fhashdict[ftype][fname] if h in myhashkeys]:
+				myhashkeys.remove(k)
+		myhashes = perform_multiple_checksums(self._getAbsname(ftype, fname), myhashkeys)
+		self.fhashdict[ftype][fname].update(myhashes)
+	
+	def updateTypeHashes(self, idtype, checkExisting=False, ignoreMissingFiles=True):
+		""" Regenerate all hashes for all files of the given type """
+		for fname in self.fhashdict[idtype]:
+			self.updateFileHashes(idtype, fname, checkExisting)
+	
+	def updateAllHashes(self, checkExisting=False, ignoreMissingFiles=True):
+		""" Regenerate all hashes for all files in this Manifest. """
+		for ftype in portage_const.MANIFEST2_IDENTIFIERS:
+			self.updateTypeHashes(idtype, fname, checkExisting)
+
+	def updateCpvHashes(self, cpv, ignoreMissingFiles=True):
+		""" Regenerate all hashes associated to the given cpv (includes all AUX and MISC
+		files)."""
+		self.updateTypeHashes("AUX", ignoreMissingFiles=ignoreMissingFiles)
+		self.updateTypeHashes("MISC", ignoreMissingFiles=ignoreMissingFiles)
+		ebuildname = "%s.ebuild" % self._catsplit(cpv)[1]
+		self.updateFileHashes("EBUILD", ebuildname, ignoreMissingFiles=ignoreMissingFiles)
+		for f in self._getCpvDistfiles(cpv):
+			self.updateFileHashes("DIST", f, ignoreMissingFiles=ignoreMissingFiles)
+
+	def updateHashesGuessType(self, fname, *args, **kwargs):
+		""" Regenerate hashes for the given file (guesses the type and then
+		calls updateFileHashes)."""
+		mytype = self.guessType(fname)
+		if mytype == "AUX":
+			fname = fname[len("files" + os.sep):]
+		elif mytype is None:
+			return
+		myrealtype = self.findFile(fname)
+		if myrealtype is not None:
+			mytype = myrealtype
+		return self.updateFileHashes(mytype, fname, *args, **kwargs)
+
+	def getFileData(self, ftype, fname, key):
+		""" Return the value of a specific (type,filename,key) triple, mainly useful
+		to get the size for distfiles."""
+		return self.fhashdict[ftype][fname][key]
+
+	def getVersions(self):
+		""" Returns a list of manifest versions present in the manifest file. """
+		rVal = []
+		mfname = self.getFullname()
+		if not os.path.exists(mfname):
+			return rVal
+		myfile = open(mfname, "r")
+		lines = myfile.readlines()
+		myfile.close()
+		for l in lines:
+			mysplit = l.split()
+			if len(mysplit) == 4 and mysplit[0] in portage_const.MANIFEST1_HASH_FUNCTIONS and not 1 in rVal:
+				rVal.append(1)
+			elif len(mysplit) > 4 and mysplit[0] in portage_const.MANIFEST2_IDENTIFIERS and ((len(mysplit) - 3) % 2) == 0 and not 2 in rVal:
+				rVal.append(2)
+		return rVal
+
+	def _catsplit(self, pkg_key):
+		"""Split a category and package, returning a list of [cat, pkg].
+		This is compatible with portage.catsplit()"""
+		return pkg_key.split("/", 1)
Index: /vendor/portage/current/pym/portage_selinux.py
===================================================================
--- /vendor/portage/current/pym/portage_selinux.py	(revision 3419)
+++ /vendor/portage/current/pym/portage_selinux.py	(revision 3419)
@@ -0,0 +1,8 @@
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+import selinux
+from selinux import is_selinux_enabled
+from selinux_aux import setexec, secure_symlink, secure_rename, \
+	secure_copy, secure_mkdir, getcontext, get_sid, get_lsid
Index: /vendor/portage/current/pym/portage_update.py
===================================================================
--- /vendor/portage/current/pym/portage_update.py	(revision 3419)
+++ /vendor/portage/current/pym/portage_update.py	(revision 3419)
@@ -0,0 +1,224 @@
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+import errno, os, re, sys
+
+from portage_util import ConfigProtect, grabfile, new_protect_filename, \
+	normalize_path, write_atomic, writemsg
+from portage_exception import DirectoryNotFound, PortageException
+from portage_versions import ververify
+from portage_dep import dep_getkey, get_operator, isvalidatom, isjustname
+from portage_const import USER_CONFIG_PATH, WORLD_FILE
+
+ignored_dbentries = ("CONTENTS", "environment.bz2")
+
+def update_dbentry(update_cmd, mycontent):
+	if update_cmd[0] == "move":
+		old_value, new_value = update_cmd[1], update_cmd[2]
+		if mycontent.count(old_value):
+			old_value = re.escape(old_value);
+			mycontent = re.sub(old_value+"(:|$|\\s)", new_value+"\\1", mycontent)
+			def myreplace(matchobj):
+				if ververify(matchobj.group(2)):
+					return "%s-%s" % (new_value, matchobj.group(2))
+				else:
+					return "".join(matchobj.groups())
+			mycontent = re.sub("(%s-)(\\S*)" % old_value, myreplace, mycontent)
+	elif update_cmd[0] == "slotmove" and get_operator(update_cmd[1]) is None:
+		pkg, origslot, newslot = update_cmd[1:]
+		old_value = "%s:%s" % (pkg, origslot)
+		if mycontent.count(old_value):
+			old_value = re.escape(old_value)
+			new_value = "%s:%s" % (pkg, newslot)
+			mycontent = re.sub(old_value+"($|\\s)", new_value+"\\1", mycontent)
+	return mycontent
+
+def update_dbentries(update_iter, mydata):
+	"""Performs update commands and returns a
+	dict containing only the updated items."""
+	updated_items = {}
+	for k, mycontent in mydata.iteritems():
+		if k not in ignored_dbentries:
+			orig_content = mycontent
+			for update_cmd in update_iter:
+				mycontent = update_dbentry(update_cmd, mycontent)
+			if mycontent != orig_content:
+				updated_items[k] = mycontent
+	return updated_items
+
+def fixdbentries(update_iter, dbdir):
+	"""Performs update commands which result in search and replace operations
+	for each of the files in dbdir (excluding CONTENTS and environment.bz2).
+	Returns True when actual modifications are necessary and False otherwise."""
+	mydata = {}
+	for myfile in [f for f in os.listdir(dbdir) if f not in ignored_dbentries]:
+		file_path = os.path.join(dbdir, myfile)
+		f = open(file_path, "r")
+		mydata[myfile] = f.read()
+		f.close()
+	updated_items = update_dbentries(update_iter, mydata)
+	for myfile, mycontent in updated_items.iteritems():
+		file_path = os.path.join(dbdir, myfile)
+		write_atomic(file_path, mycontent)
+	return len(updated_items) > 0
+
+def grab_updates(updpath, prev_mtimes=None):
+	"""Returns all the updates from the given directory as a sorted list of
+	tuples, each containing (file_path, statobj, content).  If prev_mtimes is
+	given then only updates with differing mtimes are considered."""
+	try:
+		mylist = os.listdir(updpath)
+	except OSError, oe:
+		if oe.errno == errno.ENOENT:
+			raise DirectoryNotFound(updpath)
+		raise
+	if prev_mtimes is None:
+		prev_mtimes = {}
+	# validate the file name (filter out CVS directory, etc...)
+	mylist = [myfile for myfile in mylist if len(myfile) == 7 and myfile[1:3] == "Q-"]
+	if len(mylist) == 0:
+		return []
+	
+	# update names are mangled to make them sort properly
+	mylist = [myfile[3:]+"-"+myfile[:2] for myfile in mylist]
+	mylist.sort()
+	mylist = [myfile[5:]+"-"+myfile[:4] for myfile in mylist]
+
+	update_data = []
+	for myfile in mylist:
+		file_path = os.path.join(updpath, myfile)
+		mystat = os.stat(file_path)
+		if file_path not in prev_mtimes or \
+		long(prev_mtimes[file_path]) != long(mystat.st_mtime):
+			f = open(file_path)
+			content = f.read()
+			f.close()
+			update_data.append((file_path, mystat, content))
+	return update_data
+
+def parse_updates(mycontent):
+	"""Valid updates are returned as a list of split update commands."""
+	myupd = []
+	errors = []
+	mylines = mycontent.splitlines()
+	for myline in mylines:
+		mysplit = myline.split()
+		if len(mysplit) == 0:
+			continue
+		if mysplit[0] not in ("move", "slotmove"):
+			errors.append("ERROR: Update type not recognized '%s'" % myline)
+			continue
+		if mysplit[0] == "move":
+			if len(mysplit) != 3:
+				errors.append("ERROR: Update command invalid '%s'" % myline)
+				continue
+			orig_value, new_value = mysplit[1], mysplit[2]
+			for cp in (orig_value, new_value):
+				if not (isvalidatom(cp) and isjustname(cp)):
+					errors.append(
+						"ERROR: Malformed update entry '%s'" % myline)
+					continue
+		if mysplit[0] == "slotmove":
+			if len(mysplit)!=4:
+				errors.append("ERROR: Update command invalid '%s'" % myline)
+				continue
+			pkg, origslot, newslot = mysplit[1], mysplit[2], mysplit[3]
+			if not isvalidatom(pkg):
+				errors.append("ERROR: Malformed update entry '%s'" % myline)
+				continue
+		
+		# The list of valid updates is filtered by continue statements above.
+		myupd.append(mysplit)
+	return myupd, errors
+
+def update_config_files(config_root, protect, protect_mask, update_iter):
+	"""Perform global updates on /etc/portage/package.* and the world file.
+	config_root - location of files to update
+	protect - list of paths from CONFIG_PROTECT
+	protect_mask - list of paths from CONFIG_PROTECT_MASK
+	update_iter - list of update commands as returned from parse_updates()"""
+	config_root = normalize_path(config_root)
+	update_files = {}
+	file_contents = {}
+	myxfiles = ["package.mask", "package.unmask", \
+		"package.keywords", "package.use"]
+	myxfiles += [os.path.join("profile", x) for x in myxfiles]
+	abs_user_config = os.path.join(config_root,
+		USER_CONFIG_PATH.lstrip(os.path.sep))
+	recursivefiles = []
+	for x in myxfiles:
+		config_file = os.path.join(abs_user_config, x)
+		if os.path.isdir(config_file):
+			for parent, dirs, files in os.walk(config_file):
+				for y in dirs:
+					if y.startswith("."):
+						dirs.remove(y)
+				for y in files:
+					if y.startswith("."):
+						continue
+					recursivefiles.append(
+						os.path.join(parent, y)[len(abs_user_config) + 1:])
+		else:
+			recursivefiles.append(x)
+	myxfiles = recursivefiles
+	for x in myxfiles:
+		try:
+			myfile = open(os.path.join(abs_user_config, x),"r")
+			file_contents[x] = myfile.readlines()
+			myfile.close()
+		except IOError:
+			if file_contents.has_key(x):
+				del file_contents[x]
+			continue
+	worldlist = grabfile(os.path.join(config_root, WORLD_FILE))
+
+	for update_cmd in update_iter:
+		if update_cmd[0] == "move":
+			old_value, new_value = update_cmd[1], update_cmd[2]
+			#update world entries:
+			for x in range(0,len(worldlist)):
+				#update world entries, if any.
+				worldlist[x] = \
+					dep_transform(worldlist[x], old_value, new_value)
+
+			#update /etc/portage/packages.*
+			for x in file_contents:
+				for mypos in range(0,len(file_contents[x])):
+					line = file_contents[x][mypos]
+					if line[0] == "#" or not line.strip():
+						continue
+					myatom = line.split()[0]
+					if myatom.startswith("-"):
+						# package.mask supports incrementals
+						myatom = myatom[1:]
+					if not isvalidatom(myatom):
+						continue
+					key = dep_getkey(myatom)
+					if key == old_value:
+						file_contents[x][mypos] = \
+							line.replace(old_value, new_value)
+						update_files[x] = 1
+						sys.stdout.write("p")
+						sys.stdout.flush()
+
+	write_atomic(os.path.join(config_root, WORLD_FILE), "\n".join(worldlist))
+
+	protect_obj = ConfigProtect(
+		config_root, protect, protect_mask)
+	for x in update_files:
+		updating_file = os.path.join(abs_user_config, x)
+		if protect_obj.isprotected(updating_file):
+			updating_file = new_protect_filename(updating_file)
+		try:
+			write_atomic(updating_file, "".join(file_contents[x]))
+		except PortageException, e:
+			writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
+			writemsg("!!! An error occured while updating a config file:" + \
+				" '%s'\n" % updating_file, noiselevel=-1)
+			continue
+
+def dep_transform(mydep, oldkey, newkey):
+	if dep_getkey(mydep) == oldkey:
+		return mydep.replace(oldkey, newkey, 1)
+	return mydep
Index: /vendor/portage/current/pym/portage_util.py
===================================================================
--- /vendor/portage/current/pym/portage_util.py	(revision 3419)
+++ /vendor/portage/current/pym/portage_util.py	(revision 3419)
@@ -0,0 +1,1037 @@
+# Copyright 2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: portage_util.py 5609 2007-01-12 11:53:27Z zmedico $
+
+from portage_exception import PortageException, FileNotFound, \
+       OperationNotPermitted, PermissionDenied, ReadOnlyFileSystem
+import portage_exception
+from portage_dep import isvalidatom
+
+import os, errno, shlex, stat, string, sys
+try:
+	import cPickle
+except ImportError:
+	import pickle as cPickle
+
+if not hasattr(__builtins__, "set"):
+	from sets import Set as set
+
+noiselimit = 0
+
+def writemsg(mystr,noiselevel=0,fd=None):
+	"""Prints out warning and debug messages based on the noiselimit setting"""
+	global noiselimit
+	if fd is None:
+		fd = sys.stderr
+	if noiselevel <= noiselimit:
+		fd.write(mystr)
+		fd.flush()
+
+def writemsg_stdout(mystr,noiselevel=0):
+	"""Prints messages stdout based on the noiselimit setting"""
+	writemsg(mystr, noiselevel=noiselevel, fd=sys.stdout)
+
+def normalize_path(mypath):
+	""" 
+	os.path.normpath("//foo") returns "//foo" instead of "/foo"
+	We dislike this behavior so we create our own normpath func
+	to fix it.
+	"""
+	if mypath.startswith(os.path.sep):
+		# posixpath.normpath collapses 3 or more leading slashes to just 1.
+		return os.path.normpath(2*os.path.sep + mypath)
+	else:
+		return os.path.normpath(mypath)
+
+def grabfile(myfilename, compat_level=0, recursive=0):
+	"""This function grabs the lines in a file, normalizes whitespace and returns lines in a list; if a line
+	begins with a #, it is ignored, as are empty lines"""
+
+	mylines=grablines(myfilename, recursive)
+	newlines=[]
+	for x in mylines:
+		#the split/join thing removes leading and trailing whitespace, and converts any whitespace in the line
+		#into single spaces.
+		myline=" ".join(x.split())
+		if not len(myline):
+			continue
+		if myline[0]=="#":
+			# Check if we have a compat-level string. BC-integration data.
+			# '##COMPAT==>N<==' 'some string attached to it'
+			mylinetest = myline.split("<==",1)
+			if len(mylinetest) == 2:
+				myline_potential = mylinetest[1]
+				mylinetest = mylinetest[0].split("##COMPAT==>")
+				if len(mylinetest) == 2:
+					if compat_level >= int(mylinetest[1]):
+						# It's a compat line, and the key matches.
+						newlines.append(myline_potential)
+				continue
+			else:
+				continue
+		newlines.append(myline)
+	return newlines
+
+def map_dictlist_vals(func,myDict):
+	"""Performs a function on each value of each key in a dictlist.
+	Returns a new dictlist."""
+	new_dl = {}
+	for key in myDict.keys():
+		new_dl[key] = []
+		new_dl[key] = map(func,myDict[key])
+	return new_dl
+
+def stack_dictlist(original_dicts, incremental=0, incrementals=[], ignore_none=0):
+	"""
+	Stacks an array of dict-types into one array. Optionally merging or
+	overwriting matching key/value pairs for the dict[key]->list.
+	Returns a single dict. Higher index in lists is preferenced.
+	
+	Example usage:
+	   >>> from portage_util import stack_dictlist
+		>>> print stack_dictlist( [{'a':'b'},{'x':'y'}])
+		>>> {'a':'b','x':'y'}
+		>>> print stack_dictlist( [{'a':'b'},{'a':'c'}], incremental = True )
+		>>> {'a':['b','c'] }
+		>>> a = {'KEYWORDS':['x86','alpha']}
+		>>> b = {'KEYWORDS':['-x86']}
+		>>> print stack_dictlist( [a,b] )
+		>>> { 'KEYWORDS':['x86','alpha','-x86']}
+		>>> print stack_dictlist( [a,b], incremental=True)
+		>>> { 'KEYWORDS':['alpha'] }
+		>>> print stack_dictlist( [a,b], incrementals=['KEYWORDS'])
+		>>> { 'KEYWORDS':['alpha'] }
+	
+	@param original_dicts a list of (dictionary objects or None)
+	@type list
+	@param incremental True or false depending on whether new keys should overwrite
+	   keys which already exist.
+	@type boolean
+	@param incrementals A list of items that should be incremental (-foo removes foo from
+	   the returned dict).
+	@type list
+	@param ignore_none Appears to be ignored, but probably was used long long ago.
+	@type boolean
+	
+	"""
+	final_dict = {}
+	for mydict in original_dicts:
+		if mydict is None:
+			continue
+		for y in mydict.keys():
+			if not y in final_dict:
+				final_dict[y] = []
+			
+			for thing in mydict[y]:
+				if thing:
+					if incremental or y in incrementals:
+						if thing == "-*":
+							final_dict[y] = []
+							continue
+						elif thing.startswith("-"):
+							try:
+								final_dict[y].remove(thing[1:])
+							except ValueError:
+								pass
+							continue
+					if thing not in final_dict[y]:
+						final_dict[y].append(thing)
+			if y in final_dict and not final_dict[y]:
+				del final_dict[y]
+	return final_dict
+
+def stack_dicts(dicts, incremental=0, incrementals=[], ignore_none=0):
+	"""Stacks an array of dict-types into one array. Optionally merging or
+	overwriting matching key/value pairs for the dict[key]->string.
+	Returns a single dict."""
+	final_dict = None
+	for mydict in dicts:
+		if mydict is None:
+			if ignore_none:
+				continue
+			else:
+				return None
+		if final_dict is None:
+			final_dict = {}
+		for y in mydict.keys():
+			if mydict[y]:
+				if final_dict.has_key(y) and (incremental or (y in incrementals)):
+					final_dict[y] += " "+mydict[y][:]
+				else:
+					final_dict[y]  = mydict[y][:]
+			mydict[y] = " ".join(mydict[y].split()) # Remove extra spaces.
+	return final_dict
+
+def stack_lists(lists, incremental=1):
+	"""Stacks an array of list-types into one array. Optionally removing
+	distinct values using '-value' notation. Higher index is preferenced.
+
+	all elements must be hashable."""
+
+	new_list = {}
+	for x in lists:
+		for y in filter(None, x):
+			if incremental:
+				if y == "-*":
+					new_list.clear()
+				elif y.startswith("-"):
+					new_list.pop(y[1:], None)
+				else:
+					new_list[y] = True
+			else:
+				new_list[y] = True
+	return new_list.keys()
+
+def grabdict(myfilename, juststrings=0, empty=0, recursive=0, incremental=1):
+	"""
+	This function grabs the lines in a file, normalizes whitespace and returns lines in a dictionary
+	
+	@param myfilename: file to process
+	@type myfilename: string (path)
+	@param juststrings: only return strings
+	@type juststrings: Boolean (integer)
+	@param empty: Ignore certain lines
+	@type empty: Boolean (integer)
+	@param recursive: Recursively grab ( support for /etc/portage/package.keywords/* and friends )
+	@type recursive: Boolean (integer)
+	@param incremental: Append to the return list, don't overwrite
+	@type incremental: Boolean (integer)
+	@rtype: Dictionary
+	@returns:
+	1.  Returns the lines in a file in a dictionary, for example:
+		'sys-apps/portage x86 amd64 ppc'
+		would return
+		{ "sys-apps/portage" : [ 'x86', 'amd64', 'ppc' ]
+		the line syntax is key : [list of values]
+	"""
+	newdict={}
+	for x in grablines(myfilename, recursive):
+		#the split/join thing removes leading and trailing whitespace, and converts any whitespace in the line
+		#into single spaces.
+		if x[0] == "#":
+			continue
+		myline=x.split()
+		if len(myline) < 2 and empty == 0:
+			continue
+		if len(myline) < 1 and empty == 1:
+			continue
+		if incremental:
+			newdict.setdefault(myline[0], []).extend(myline[1:])
+		else:
+			newdict[myline[0]] = myline[1:]
+	if juststrings:
+		for k, v in newdict.iteritems():
+			newdict[k] = " ".join(v)
+	return newdict
+
+def grabdict_package(myfilename, juststrings=0, recursive=0):
+	pkgs=grabdict(myfilename, juststrings, empty=1, recursive=recursive)
+	# We need to call keys() here in order to avoid the possibility of
+	# "RuntimeError: dictionary changed size during iteration"
+	# when an invalid atom is deleted.
+	for x in pkgs.keys():
+		if not isvalidatom(x):
+			del(pkgs[x])
+			writemsg("--- Invalid atom in %s: %s\n" % (myfilename, x),
+				noiselevel=-1)
+	return pkgs
+
+def grabfile_package(myfilename, compatlevel=0, recursive=0):
+	pkgs=grabfile(myfilename, compatlevel, recursive=recursive)
+	for x in range(len(pkgs)-1, -1, -1):
+		pkg = pkgs[x]
+		if pkg[0] == "-":
+			pkg = pkg[1:]
+		if pkg[0] == "*": # Kill this so we can deal the "packages" file too
+			pkg = pkg[1:]
+		if not isvalidatom(pkg):
+			writemsg("--- Invalid atom in %s: %s\n" % (myfilename, pkgs[x]),
+				noiselevel=-1)
+			del(pkgs[x])
+	return pkgs
+
+def grablines(myfilename,recursive=0):
+	mylines=[]
+	if recursive and os.path.isdir(myfilename):
+		if myfilename in ["RCS", "CVS", "SCCS"]:
+			return mylines
+		dirlist = os.listdir(myfilename)
+		dirlist.sort()
+		for f in dirlist:
+			if not f.startswith(".") and not f.endswith("~"):
+				mylines.extend(grablines(
+					os.path.join(myfilename, f), recursive))
+	else:
+		try:
+			myfile = open(myfilename, "r")
+			mylines = myfile.readlines()
+			myfile.close()
+		except IOError:
+			pass
+	return mylines
+
+def writedict(mydict,myfilename,writekey=True):
+	"""Writes out a dict to a file; writekey=0 mode doesn't write out
+	the key and assumes all values are strings, not lists."""
+	myfile = None
+	try:
+		myfile = atomic_ofstream(myfilename)
+		if not writekey:
+			for x in mydict.values():
+				myfile.write(x+"\n")
+		else:
+			for x in mydict.keys():
+				myfile.write("%s %s\n" % (x, " ".join(mydict[x])))
+		myfile.close()
+	except IOError:
+		if myfile is not None:
+			myfile.abort()
+		return 0
+	return 1
+
+def getconfig(mycfg, tolerant=0, allow_sourcing=False, expand=True):
+	mykeys={}
+	try:
+		f=open(mycfg,'r')
+	except IOError, e:
+		if e.errno != errno.ENOENT:
+			raise
+		return None
+	try:
+		lex = shlex.shlex(f, posix=True)
+		lex.wordchars=string.digits+string.letters+"~!@#$%*_\:;?,./-+{}"     
+		lex.quotes="\"'"
+		if allow_sourcing:
+			lex.source="source"
+		while 1:
+			key=lex.get_token()
+			if key == "export":
+				key = lex.get_token()
+			if key is None:
+				#normal end of file
+				break;
+			equ=lex.get_token()
+			if (equ==''):
+				#unexpected end of file
+				#lex.error_leader(self.filename,lex.lineno)
+				if not tolerant:
+					writemsg("!!! Unexpected end of config file: variable "+str(key)+"\n",
+						noiselevel=-1)
+					raise Exception("ParseError: Unexpected EOF: "+str(mycfg)+": on/before line "+str(lex.lineno))
+				else:
+					return mykeys
+			elif (equ!='='):
+				#invalid token
+				#lex.error_leader(self.filename,lex.lineno)
+				if not tolerant:
+					writemsg("!!! Invalid token (not \"=\") "+str(equ)+"\n",
+						noiselevel=-1)
+					raise Exception("ParseError: Invalid token (not '='): "+str(mycfg)+": line "+str(lex.lineno))
+				else:
+					return mykeys
+			val=lex.get_token()
+			if val is None:
+				#unexpected end of file
+				#lex.error_leader(self.filename,lex.lineno)
+				if not tolerant:
+					writemsg("!!! Unexpected end of config file: variable "+str(key)+"\n",
+						noiselevel=-1)
+					raise portage_exception.CorruptionError("ParseError: Unexpected EOF: "+str(mycfg)+": line "+str(lex.lineno))
+				else:
+					return mykeys
+			if expand:
+				mykeys[key] = varexpand(val, mykeys)
+			else:
+				mykeys[key] = val
+	except SystemExit, e:
+		raise
+	except Exception, e:
+		raise portage_exception.ParseError(str(e)+" in "+mycfg)
+	return mykeys
+	
+#cache expansions of constant strings
+cexpand={}
+def varexpand(mystring,mydict={}):
+	newstring = cexpand.get(" "+mystring, None)
+	if newstring is not None:
+		return newstring
+
+	"""
+	new variable expansion code.  Removes quotes, handles \n, etc.
+	This code is used by the configfile code, as well as others (parser)
+	This would be a good bunch of code to port to C.
+	"""
+	numvars=0
+	mystring=" "+mystring
+	#in single, double quotes
+	insing=0
+	indoub=0
+	pos=1
+	newstring=" "
+	while (pos<len(mystring)):
+		if (mystring[pos]=="'") and (mystring[pos-1]!="\\"):
+			if (indoub):
+				newstring=newstring+"'"
+			else:
+				insing=not insing
+			pos=pos+1
+			continue
+		elif (mystring[pos]=='"') and (mystring[pos-1]!="\\"):
+			if (insing):
+				newstring=newstring+'"'
+			else:
+				indoub=not indoub
+			pos=pos+1
+			continue
+		if (not insing): 
+			#expansion time
+			if (mystring[pos]=="\n"):
+				#convert newlines to spaces
+				newstring=newstring+" "
+				pos=pos+1
+			elif (mystring[pos]=="\\"):
+				#backslash expansion time
+				if (pos+1>=len(mystring)):
+					newstring=newstring+mystring[pos]
+					break
+				else:
+					a=mystring[pos+1]
+					pos=pos+2
+					if a=='a':
+						newstring=newstring+chr(007)
+					elif a=='b':
+						newstring=newstring+chr(010)
+					elif a=='e':
+						newstring=newstring+chr(033)
+					elif (a=='f') or (a=='n'):
+						newstring=newstring+chr(012)
+					elif a=='r':
+						newstring=newstring+chr(015)
+					elif a=='t':
+						newstring=newstring+chr(011)
+					elif a=='v':
+						newstring=newstring+chr(013)
+					elif a!='\n':
+						#remove backslash only, as bash does: this takes care of \\ and \' and \" as well
+						newstring=newstring+mystring[pos-1:pos]
+						continue
+			elif (mystring[pos]=="$") and (mystring[pos-1]!="\\"):
+				pos=pos+1
+				if mystring[pos]=="{":
+					pos=pos+1
+					braced=True
+				else:
+					braced=False
+				myvstart=pos
+				validchars=string.ascii_letters+string.digits+"_"
+				while mystring[pos] in validchars:
+					if (pos+1)>=len(mystring):
+						if braced:
+							cexpand[mystring]=""
+							return ""
+						else:
+							pos=pos+1
+							break
+					pos=pos+1
+				myvarname=mystring[myvstart:pos]
+				if braced:
+					if mystring[pos]!="}":
+						cexpand[mystring]=""
+						return ""
+					else:
+						pos=pos+1
+				if len(myvarname)==0:
+					cexpand[mystring]=""
+					return ""
+				numvars=numvars+1
+				if mydict.has_key(myvarname):
+					newstring=newstring+mydict[myvarname] 
+			else:
+				newstring=newstring+mystring[pos]
+				pos=pos+1
+		else:
+			newstring=newstring+mystring[pos]
+			pos=pos+1
+	if numvars==0:
+		cexpand[mystring]=newstring[1:]
+	return newstring[1:]	
+
+def pickle_write(data,filename,debug=0):
+	import os
+	try:
+		myf=open(filename,"w")
+		cPickle.dump(data,myf,-1)
+		myf.flush()
+		myf.close()
+		writemsg("Wrote pickle: "+str(filename)+"\n",1)
+		os.chown(myefn,uid,portage_gid)
+		os.chmod(myefn,0664)
+	except SystemExit, e:
+		raise
+	except Exception, e:
+		return 0
+	return 1
+
+def pickle_read(filename,default=None,debug=0):
+	import os
+	if not os.access(filename, os.R_OK):
+		writemsg("pickle_read(): File not readable. '"+filename+"'\n",1)
+		return default
+	data = None
+	try:
+		myf = open(filename)
+		mypickle = cPickle.Unpickler(myf)
+		mypickle.find_global = None
+		data = mypickle.load()
+		myf.close()
+		del mypickle,myf
+		writemsg("pickle_read(): Loaded pickle. '"+filename+"'\n",1)
+	except SystemExit, e:
+		raise
+	except Exception, e:
+		writemsg("!!! Failed to load pickle: "+str(e)+"\n",1)
+		data = default
+	return data
+
+def dump_traceback(msg, noiselevel=1):
+	import sys, traceback
+	info = sys.exc_info()
+	if not info[2]:
+		stack = traceback.extract_stack()[:-1]
+		error = None
+	else:
+		stack = traceback.extract_tb(info[2])
+		error = str(info[1])
+	writemsg("\n====================================\n", noiselevel=noiselevel)
+	writemsg("%s\n\n" % msg, noiselevel=noiselevel)
+	for line in traceback.format_list(stack):
+		writemsg(line, noiselevel=noiselevel)
+	if error:
+		writemsg(error+"\n", noiselevel=noiselevel)
+	writemsg("====================================\n\n", noiselevel=noiselevel)
+
+def unique_array(s):
+	"""lifted from python cookbook, credit: Tim Peters
+	Return a list of the elements in s in arbitrary order, sans duplicates"""
+	n = len(s)
+	# assume all elements are hashable, if so, it's linear
+	try:
+		return list(set(s))
+	except TypeError:
+		pass
+
+	# so much for linear.  abuse sort.
+	try:
+		t = list(s)
+		t.sort()
+	except TypeError:
+		pass
+	else:
+		assert n > 0
+		last = t[0]
+		lasti = i = 1
+		while i < n:
+			if t[i] != last:
+				t[lasti] = last = t[i]
+				lasti += 1
+			i += 1
+		return t[:lasti]
+
+	# blah.	 back to original portage.unique_array
+	u = []
+	for x in s:
+		if x not in u:
+			u.append(x)
+	return u
+
+def apply_permissions(filename, uid=-1, gid=-1, mode=-1, mask=-1,
+	stat_cached=None, follow_links=True):
+	"""Apply user, group, and mode bits to a file if the existing bits do not
+	already match.  The default behavior is to force an exact match of mode
+	bits.  When mask=0 is specified, mode bits on the target file are allowed
+	to be a superset of the mode argument (via logical OR).  When mask>0, the
+	mode bits that the target file is allowed to have are restricted via
+	logical XOR.
+	Returns True if the permissions were modified and False otherwise."""
+
+	modified = False
+
+	if stat_cached is None:
+		try:
+			if follow_links:
+				stat_cached = os.stat(filename)
+			else:
+				stat_cached = os.lstat(filename)
+		except OSError, oe:
+			func_call = "stat('%s')" % filename
+			if oe.errno == errno.EPERM:
+				raise OperationNotPermitted(func_call)
+			elif oe.errno == errno.EACCES:
+				raise PermissionDenied(func_call)
+			elif oe.errno == errno.ENOENT:
+				raise FileNotFound(filename)
+			else:
+				raise
+
+	if	(uid != -1 and uid != stat_cached.st_uid) or \
+		(gid != -1 and gid != stat_cached.st_gid):
+		try:
+			if follow_links:
+				os.chown(filename, uid, gid)
+			else:
+				import portage_data
+				portage_data.lchown(filename, uid, gid)
+			modified = True
+		except OSError, oe:
+			func_call = "chown('%s', %i, %i)" % (filename, uid, gid)
+			if oe.errno == errno.EPERM:
+				raise OperationNotPermitted(func_call)
+			elif oe.errno == errno.EACCES:
+				raise PermissionDenied(func_call)
+			elif oe.errno == errno.EROFS:
+				raise ReadOnlyFileSystem(func_call)
+			elif oe.errno == errno.ENOENT:
+				raise FileNotFound(filename)
+			else:
+				raise
+
+	new_mode = -1
+	st_mode = stat_cached.st_mode & 07777 # protect from unwanted bits
+	if mask >= 0:
+		if mode == -1:
+			mode = 0 # Don't add any mode bits when mode is unspecified.
+		else:
+			mode = mode & 07777
+		if	(mode & st_mode != mode) or \
+			((mask ^ st_mode) & st_mode != st_mode):
+			new_mode = mode | st_mode
+			new_mode = (mask ^ new_mode) & new_mode
+	elif mode != -1:
+		mode = mode & 07777 # protect from unwanted bits
+		if mode != st_mode:
+			new_mode = mode
+
+	# The chown system call may clear S_ISUID and S_ISGID
+	# bits, so those bits are restored if necessary.
+	if modified and new_mode == -1 and \
+		(st_mode & stat.S_ISUID or st_mode & stat.S_ISGID):
+		if mode == -1:
+			new_mode = st_mode
+		else:
+			mode = mode & 07777
+			if mask >= 0:
+				new_mode = mode | st_mode
+				new_mode = (mask ^ new_mode) & new_mode
+			else:
+				new_mode = mode
+			if not (new_mode & stat.S_ISUID or new_mode & stat.S_ISGID):
+				new_mode = -1
+
+	if not follow_links and stat.S_ISLNK(stat_cached.st_mode):
+		# Mode doesn't matter for symlinks.
+		new_mode = -1
+
+	if new_mode != -1:
+		try:
+			os.chmod(filename, new_mode)
+			modified = True
+		except OSError, oe:
+			func_call = "chmod('%s', %s)" % (filename, oct(new_mode))
+			if oe.errno == errno.EPERM:
+				raise OperationNotPermitted(func_call)
+			elif oe.errno == errno.EACCES:
+				raise PermissionDenied(func_call)
+			elif oe.errno == errno.EROFS:
+				raise ReadOnlyFileSystem(func_call)
+			elif oe.errno == errno.ENOENT:
+				raise FileNotFound(filename)
+			raise
+	return modified
+
+def apply_stat_permissions(filename, newstat, **kwargs):
+	"""A wrapper around apply_secpass_permissions that gets
+	uid, gid, and mode from a stat object"""
+	return apply_secpass_permissions(filename, uid=newstat.st_uid, gid=newstat.st_gid,
+	mode=newstat.st_mode, **kwargs)
+
+def apply_recursive_permissions(top, uid=-1, gid=-1,
+	dirmode=-1, dirmask=-1, filemode=-1, filemask=-1, onerror=None):
+	"""A wrapper around apply_secpass_permissions that applies permissions
+	recursively.  If optional argument onerror is specified, it should be a
+	function; it will be called with one argument, a PortageException instance.
+	Returns True if all permissions are applied and False if some are left
+	unapplied."""
+
+	if onerror is None:
+		# Default behavior is to dump errors to stderr so they won't
+		# go unnoticed.  Callers can pass in a quiet instance.
+		def onerror(e):
+			if isinstance(e, OperationNotPermitted):
+				writemsg("Operation Not Permitted: %s\n" % str(e),
+					noiselevel=-1)
+			elif isinstance(e, FileNotFound):
+				writemsg("File Not Found: '%s'\n" % str(e), noiselevel=-1)
+			else:
+				raise
+
+	all_applied = True
+	for dirpath, dirnames, filenames in os.walk(top):
+		try:
+			applied = apply_secpass_permissions(dirpath,
+				uid=uid, gid=gid, mode=dirmode, mask=dirmask)
+			if not applied:
+				all_applied = False
+		except PortageException, e:
+			all_applied = False
+			onerror(e)
+
+		for name in filenames:
+			try:
+				applied = apply_secpass_permissions(os.path.join(dirpath, name),
+					uid=uid, gid=gid, mode=filemode, mask=filemask)
+				if not applied:
+					all_applied = False
+			except PortageException, e:
+				all_applied = False
+				onerror(e)
+	return all_applied
+
+def apply_secpass_permissions(filename, uid=-1, gid=-1, mode=-1, mask=-1,
+	stat_cached=None, follow_links=True):
+	"""A wrapper around apply_permissions that uses secpass and simple
+	logic to apply as much of the permissions as possible without
+	generating an obviously avoidable permission exception. Despite
+	attempts to avoid an exception, it's possible that one will be raised
+	anyway, so be prepared.
+	Returns True if all permissions are applied and False if some are left
+	unapplied."""
+
+	if stat_cached is None:
+		try:
+			if follow_links:
+				stat_cached = os.stat(filename)
+			else:
+				stat_cached = os.lstat(filename)
+		except OSError, oe:
+			func_call = "stat('%s')" % filename
+			if oe.errno == errno.EPERM:
+				raise OperationNotPermitted(func_call)
+			elif oe.errno == errno.EACCES:
+				raise PermissionDenied(func_call)
+			elif oe.errno == errno.ENOENT:
+				raise FileNotFound(filename)
+			else:
+				raise
+
+	all_applied = True
+
+	import portage_data # not imported globally because of circular dep
+	if portage_data.secpass < 2:
+
+		if uid != -1 and \
+		uid != stat_cached.st_uid:
+			all_applied = False
+			uid = -1
+
+		if gid != -1 and \
+		gid != stat_cached.st_gid and \
+		gid not in os.getgroups():
+			all_applied = False
+			gid = -1
+
+	apply_permissions(filename, uid=uid, gid=gid, mode=mode, mask=mask,
+		stat_cached=stat_cached, follow_links=follow_links)
+	return all_applied
+
+class atomic_ofstream(file):
+	"""Write a file atomically via os.rename().  Atomic replacement prevents
+	interprocess interference and prevents corruption of the target
+	file when the write is interrupted (for example, when an 'out of space'
+	error occurs)."""
+
+	def __init__(self, filename, mode='w', follow_links=True, **kargs):
+		"""Opens a temporary filename.pid in the same directory as filename."""
+		self._aborted = False
+
+		if follow_links:
+			canonical_path = os.path.realpath(filename)
+			self._real_name = canonical_path
+			tmp_name = "%s.%i" % (canonical_path, os.getpid())
+			try:
+				super(atomic_ofstream, self).__init__(tmp_name, mode=mode, **kargs)
+				return
+			except (OSError, IOError), e:
+				if canonical_path == filename:
+					raise
+				writemsg("!!! Failed to open file: '%s'\n" % tmp_name,
+					noiselevel=-1)
+				writemsg("!!! %s\n" % str(e), noiselevel=-1)
+
+		self._real_name = filename
+		tmp_name = "%s.%i" % (filename, os.getpid())
+		super(atomic_ofstream, self).__init__(tmp_name, mode=mode, **kargs)
+
+	def close(self):
+		"""Closes the temporary file, copies permissions (if possible),
+		and performs the atomic replacement via os.rename().  If the abort()
+		method has been called, then the temp file is closed and removed."""
+		if not self.closed:
+			try:
+				super(atomic_ofstream, self).close()
+				if not self._aborted:
+					try:
+						apply_stat_permissions(self.name, os.stat(self._real_name))
+					except OperationNotPermitted:
+						pass
+					except FileNotFound:
+						pass
+					except OSError, oe: # from the above os.stat call
+						if oe.errno in (errno.ENOENT, errno.EPERM):
+							pass
+						else:
+							raise
+					os.rename(self.name, self._real_name)
+			finally:
+				# Make sure we cleanup the temp file
+				# even if an exception is raised.
+				try:
+					os.unlink(self.name)
+				except OSError, oe:
+					pass
+
+	def abort(self):
+		"""If an error occurs while writing the file, the user should
+		call this method in order to leave the target file unchanged.
+		This will call close() automatically."""
+		if not self._aborted:
+			self._aborted = True
+			self.close()
+
+	def __del__(self):
+		"""If the user does not explicitely call close(), it is
+		assumed that an error has occurred, so we abort()."""
+		if not self.closed:
+			self.abort()
+		# ensure destructor from the base class is called
+		base_destructor = getattr(super(atomic_ofstream, self), '__del__', None)
+		if base_destructor is not None:
+			base_destructor()
+
+def write_atomic(file_path, content):
+	f = None
+	try:
+		f = atomic_ofstream(file_path)
+		f.write(content)
+		f.close()
+	except (IOError, OSError), e:
+		if f:
+			f.abort()
+		func_call = "write_atomic('%s')" % file_path
+		if e.errno == errno.EPERM:
+			raise OperationNotPermitted(func_call)
+		elif e.errno == errno.EACCES:
+			raise PermissionDenied(func_call)
+		elif e.errno == errno.EROFS:
+			raise ReadOnlyFileSystem(func_call)
+		elif e.errno == errno.ENOENT:
+			raise FileNotFound(file_path)
+		else:
+			raise
+
+def ensure_dirs(dir_path, *args, **kwargs):
+	"""Create a directory and call apply_permissions.
+	Returns True if a directory is created or the permissions needed to be
+	modified, and False otherwise."""
+
+	created_dir = False
+
+	try:
+		os.makedirs(dir_path)
+		created_dir = True
+	except OSError, oe:
+		func_call = "makedirs('%s')" % dir_path
+		if errno.EEXIST == oe.errno:
+			pass
+		elif oe.errno == errno.EPERM:
+			raise OperationNotPermitted(func_call)
+		elif oe.errno == errno.EACCES:
+			raise PermissionDenied(func_call)
+		elif oe.errno == errno.EROFS:
+			raise ReadOnlyFileSystem(func_call)
+		else:
+			raise
+	perms_modified = apply_permissions(dir_path, *args, **kwargs)
+	return created_dir or perms_modified
+
+class LazyItemsDict(dict):
+	"""A mapping object that behaves like a standard dict except that it allows
+	for lazy initialization of values via callable objects.  Lazy items can be
+	overwritten and deleted just as normal items."""
+	def __init__(self, initial_items=None):
+		dict.__init__(self)
+		self.lazy_items = {}
+		if initial_items is not None:
+			self.update(initial_items)
+	def addLazyItem(self, item_key, value_callable, *pargs, **kwargs):
+		"""Add a lazy item for the given key.  When the item is requested,
+		value_callable will be called with *pargs and **kwargs arguments."""
+		self.lazy_items[item_key] = (value_callable, pargs, kwargs)
+		# make it show up in self.keys(), etc...
+		dict.__setitem__(self, item_key, None)
+	def addLazySingleton(self, item_key, value_callable, *pargs, **kwargs):
+		"""This is like addLazyItem except value_callable will only be called
+		a maximum of 1 time and the result will be cached for future requests."""
+		class SingletonItem(object):
+			def __init__(self, value_callable, *pargs, **kwargs):
+				self._callable = value_callable
+				self._pargs = pargs
+				self._kwargs = kwargs
+				self._called = False
+			def __call__(self):
+				if not self._called:
+					self._called = True
+					self._value = self._callable(*self._pargs, **self._kwargs)
+				return self._value
+		self.addLazyItem(item_key, SingletonItem(value_callable, *pargs, **kwargs))
+	def update(self, map_obj):
+		if isinstance(map_obj, LazyItemsDict):
+			for k in map_obj:
+				if k in map_obj.lazy_items:
+					dict.__setitem__(self, k, None)
+				else:
+					dict.__setitem__(self, k, map_obj[k])
+			self.lazy_items.update(map_obj.lazy_items)
+		else:
+			dict.update(self, map_obj)
+	def __getitem__(self, item_key):
+		if item_key in self.lazy_items:
+			value_callable, pargs, kwargs = self.lazy_items[item_key]
+			return value_callable(*pargs, **kwargs)
+		else:
+			return dict.__getitem__(self, item_key)
+	def __setitem__(self, item_key, value):
+		if item_key in self.lazy_items:
+			del self.lazy_items[item_key]
+		dict.__setitem__(self, item_key, value)
+	def __delitem__(self, item_key):
+		if item_key in self.lazy_items:
+			del self.lazy_items[item_key]
+		dict.__delitem__(self, item_key)
+
+class ConfigProtect(object):
+	def __init__(self, myroot, protect_list, mask_list):
+		self.myroot = myroot
+		self.protect_list = protect_list
+		self.mask_list = mask_list
+		self.updateprotect()
+
+	def updateprotect(self):
+		"""Update internal state for isprotected() calls.  Nonexistent paths
+		are ignored."""
+		self.protect = []
+		self._dirs = set()
+		for x in self.protect_list:
+			ppath = normalize_path(
+				os.path.join(self.myroot, x.lstrip(os.path.sep)))
+			mystat = None
+			try:
+				if stat.S_ISDIR(os.stat(ppath).st_mode):
+					self._dirs.add(ppath)
+				self.protect.append(ppath)
+			except OSError:
+				# If it doesn't exist, there's no need to protect it.
+				pass
+
+		self.protectmask = []
+		for x in self.mask_list:
+			ppath = normalize_path(
+				os.path.join(self.myroot, x.lstrip(os.path.sep)))
+			mystat = None
+			try:
+				"""Use lstat so that anything, even a broken symlink can be
+				protected."""
+				if stat.S_ISDIR(os.lstat(ppath).st_mode):
+					self._dirs.add(ppath)
+				self.protectmask.append(ppath)
+				"""Now use stat in case this is a symlink to a directory."""
+				if stat.S_ISDIR(os.stat(ppath).st_mode):
+					self._dirs.add(ppath)
+			except OSError:
+				# If it doesn't exist, there's no need to mask it.
+				pass
+
+	def isprotected(self, obj):
+		"""Returns True if obj is protected, False otherwise.  The caller must
+		ensure that obj is normalized with a single leading slash.  A trailing
+		slash is optional for directories."""
+		masked = 0
+		protected = 0
+		sep = os.path.sep
+		for ppath in self.protect:
+			if len(ppath) > masked and obj.startswith(ppath):
+				if ppath in self._dirs:
+					if obj != ppath and not obj.startswith(ppath + sep):
+						# /etc/foo does not match /etc/foobaz
+						continue
+				elif obj != ppath:
+					# force exact match when CONFIG_PROTECT lists a
+					# non-directory
+					continue
+				protected = len(ppath)
+				#config file management
+				for pmpath in self.protectmask:
+					if len(pmpath) >= protected and obj.startswith(pmpath):
+						if pmpath in self._dirs:
+							if obj != pmpath and \
+								not obj.startswith(pmpath + sep):
+								# /etc/foo does not match /etc/foobaz
+								continue
+						elif obj != pmpath:
+							# force exact match when CONFIG_PROTECT_MASK lists
+							# a non-directory
+							continue
+						#skip, it's in the mask
+						masked = len(pmpath)
+		return protected > masked
+
+def new_protect_filename(mydest, newmd5=None):
+	"""Resolves a config-protect filename for merging, optionally
+	using the last filename if the md5 matches.
+	(dest,md5) ==> 'string'            --- path_to_target_filename
+	(dest)     ==> ('next', 'highest') --- next_target and most-recent_target
+	"""
+
+	# config protection filename format:
+	# ._cfg0000_foo
+	# 0123456789012
+	prot_num = -1
+	last_pfile = ""
+
+	if not os.path.exists(mydest):
+		return mydest
+
+	real_filename = os.path.basename(mydest)
+	real_dirname  = os.path.dirname(mydest)
+	for pfile in os.listdir(real_dirname):
+		if pfile[0:5] != "._cfg":
+			continue
+		if pfile[10:] != real_filename:
+			continue
+		try:
+			new_prot_num = int(pfile[5:9])
+			if new_prot_num > prot_num:
+				prot_num = new_prot_num
+				last_pfile = pfile
+		except ValueError:
+			continue
+	prot_num = prot_num + 1
+
+	new_pfile = normalize_path(os.path.join(real_dirname,
+		"._cfg" + str(prot_num).zfill(4) + "_" + real_filename))
+	old_pfile = normalize_path(os.path.join(real_dirname, last_pfile))
+	if last_pfile and newmd5:
+		import portage_checksum
+		if portage_checksum.perform_md5(
+			os.path.join(real_dirname, last_pfile)) == newmd5:
+			return old_pfile
+	return new_pfile
Index: /vendor/portage/current/pym/portage_versions.py
===================================================================
--- /vendor/portage/current/pym/portage_versions.py	(revision 3419)
+++ /vendor/portage/current/pym/portage_versions.py	(revision 3419)
@@ -0,0 +1,316 @@
+# portage_versions.py -- core Portage functionality
+# Copyright 1998-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: portage_versions.py 5595 2007-01-12 08:08:03Z antarus $
+
+import re
+
+ver_regexp = re.compile("^(cvs\\.)?(\\d+)((\\.\\d+)*)([a-z]?)((_(pre|p|beta|alpha|rc)\\d*)*)(-r(\\d+))?$")
+suffix_regexp = re.compile("^(alpha|beta|rc|pre|p)(\\d*)$")
+suffix_value = {"pre": -2, "p": 0, "alpha": -4, "beta": -3, "rc": -1}
+endversion_keys = ["pre", "p", "alpha", "beta", "rc"]
+
+from portage_exception import InvalidData
+
+def ververify(myver, silent=1):
+	if ver_regexp.match(myver):
+		return 1
+	else:
+		if not silent:
+			print "!!! syntax error in version: %s" % myver
+		return 0
+
+vercmp_cache = {}
+def vercmp(ver1, ver2, silent=1):
+	"""
+	Compare two versions
+	Example usage:
+		>>> from portage_versions import vercmp
+		>>> vercmp('1.0-r1','1.2-r3')
+		negative number
+		>>> vercmp('1.3','1.2-r3')
+		positive number
+		>>> vercmp('1.0_p3','1.0_p3')
+		0
+	
+	@param pkg1: version to compare with (see ver_regexp in portage_versions.py)
+	@type pkg1: string (example: "2.1.2-r3")
+	@param pkg2: version to compare againts (see ver_regexp in portage_versions.py)
+	@type pkg2: string (example: "2.1.2_rc5")
+	@rtype: None or float
+	@return:
+	1. positive if ver1 is greater than ver2
+	2. negative if ver1 is less than ver2 
+	3. 0 if ver1 equals ver2
+	4. None if ver1 or ver2 are invalid (see ver_regexp in portage_versions.py)
+	"""
+
+	if ver1 == ver2:
+		return 0
+	mykey=ver1+":"+ver2
+	try:
+		return vercmp_cache[mykey]
+	except KeyError:
+		pass
+	match1 = ver_regexp.match(ver1)
+	match2 = ver_regexp.match(ver2)
+	
+	# checking that the versions are valid
+	if not match1 or not match1.groups():
+		if not silent:
+			print "!!! syntax error in version: %s" % ver1
+		return None
+	if not match2 or not match2.groups():
+		if not silent:
+			print "!!! syntax error in version: %s" % ver2
+		return None
+
+	# shortcut for cvs ebuilds (new style)
+	if match1.group(1) and not match2.group(1):
+		vercmp_cache[mykey] = 1
+		return 1
+	elif match2.group(1) and not match1.group(1):
+		vercmp_cache[mykey] = -1
+		return -1
+	
+	# building lists of the version parts before the suffix
+	# first part is simple
+	list1 = [int(match1.group(2))]
+	list2 = [int(match2.group(2))]
+
+	# this part would greatly benefit from a fixed-length version pattern
+	if len(match1.group(3)) or len(match2.group(3)):
+		vlist1 = match1.group(3)[1:].split(".")
+		vlist2 = match2.group(3)[1:].split(".")
+		for i in range(0, max(len(vlist1), len(vlist2))):
+			# Implcit .0 is given a value of -1, so that 1.0.0 > 1.0, since it
+			# would be ambiguous if two versions that aren't literally equal
+			# are given the same value (in sorting, for example).
+			if len(vlist1) <= i or len(vlist1[i]) == 0:
+				list1.append(-1)
+				list2.append(int(vlist2[i]))
+			elif len(vlist2) <= i or len(vlist2[i]) == 0:
+				list1.append(int(vlist1[i]))
+				list2.append(-1)
+			# Let's make life easy and use integers unless we're forced to use floats
+			elif (vlist1[i][0] != "0" and vlist2[i][0] != "0"):
+				list1.append(int(vlist1[i]))
+				list2.append(int(vlist2[i]))
+			# now we have to use floats so 1.02 compares correctly against 1.1
+			else:
+				list1.append(float("0."+vlist1[i]))
+				list2.append(float("0."+vlist2[i]))
+
+	# and now the final letter
+	if len(match1.group(5)):
+		list1.append(ord(match1.group(5)))
+	if len(match2.group(5)):
+		list2.append(ord(match2.group(5)))
+
+	for i in range(0, max(len(list1), len(list2))):
+		if len(list1) <= i:
+			vercmp_cache[mykey] = -1
+			return -1
+		elif len(list2) <= i:
+			vercmp_cache[mykey] = 1
+			return 1
+		elif list1[i] != list2[i]:
+			vercmp_cache[mykey] = list1[i] - list2[i]
+			return list1[i] - list2[i]
+	
+	# main version is equal, so now compare the _suffix part
+	list1 = match1.group(6).split("_")[1:]
+	list2 = match2.group(6).split("_")[1:]
+	
+	for i in range(0, max(len(list1), len(list2))):
+		# Implicit _p0 is given a value of -1, so that 1 < 1_p0
+		if len(list1) <= i:
+			s1 = ("p","-1")
+		else:
+			s1 = suffix_regexp.match(list1[i]).groups()
+		if len(list2) <= i:
+			s2 = ("p","-1")
+		else:
+			s2 = suffix_regexp.match(list2[i]).groups()
+		if s1[0] != s2[0]:
+			return suffix_value[s1[0]] - suffix_value[s2[0]]
+		if s1[1] != s2[1]:
+			# it's possible that the s(1|2)[1] == ''
+			# in such a case, fudge it.
+			try:			r1 = int(s1[1])
+			except ValueError:	r1 = 0
+			try:			r2 = int(s2[1])
+			except ValueError:	r2 = 0
+			if r1 - r2:
+				return r1 - r2
+	
+	# the suffix part is equal to, so finally check the revision
+	if match1.group(10):
+		r1 = int(match1.group(10))
+	else:
+		r1 = 0
+	if match2.group(10):
+		r2 = int(match2.group(10))
+	else:
+		r2 = 0
+	vercmp_cache[mykey] = r1 - r2
+	return r1 - r2
+	
+def pkgcmp(pkg1, pkg2):
+	"""
+	Compare 2 package versions created in pkgsplit format.
+
+	Example usage:
+		>>> from portage_versions import *
+		>>> pkgcmp(pkgsplit('test-1.0-r1'),pkgsplit('test-1.2-r3'))
+		-1
+		>>> pkgcmp(pkgsplit('test-1.3'),pkgsplit('test-1.2-r3'))
+		1
+
+	@param pkg1: package to compare with
+	@type pkg1: list (example: ['test', '1.0', 'r1'])
+	@param pkg2: package to compare againts
+	@type pkg2: list (example: ['test', '1.0', 'r1'])
+	@rtype: None or integer
+	@return: 
+		1. None if package names are not the same
+		2. 1 if pkg1 is greater than pkg2
+		3. -1 if pkg1 is less than pkg2 
+		4. 0 if pkg1 equals pkg2
+	"""
+	if pkg1[0] != pkg2[0]:
+		return None
+	mycmp=vercmp(pkg1[1],pkg2[1])
+	if mycmp>0:
+		return 1
+	if mycmp<0:
+		return -1
+	r1=float(pkg1[2][1:])
+	r2=float(pkg2[2][1:])
+	if r1>r2:
+		return 1
+	if r2>r1:
+		return -1
+	return 0
+
+
+pkgcache={}
+
+def pkgsplit(mypkg,silent=1):
+	try:
+		if not pkgcache[mypkg]:
+			return None
+		return pkgcache[mypkg][:]
+	except KeyError:
+		pass
+	myparts=mypkg.split("-")
+	
+	if len(myparts)<2:
+		if not silent:
+			print "!!! Name error in",mypkg+": missing a version or name part."
+		pkgcache[mypkg]=None
+		return None
+	for x in myparts:
+		if len(x)==0:
+			if not silent:
+				print "!!! Name error in",mypkg+": empty \"-\" part."
+			pkgcache[mypkg]=None
+			return None
+	
+	#verify rev
+	revok=0
+	myrev=myparts[-1]
+	if len(myrev) and myrev[0]=="r":
+		try:
+			int(myrev[1:])
+			revok=1
+		except ValueError: # from int()
+			pass
+	if revok:
+		verPos = -2
+		revision = myparts[-1]
+	else:
+		verPos = -1
+		revision = "r0"
+
+	if ververify(myparts[verPos]):
+		if len(myparts)== (-1*verPos):
+			pkgcache[mypkg]=None
+			return None
+		else:
+			for x in myparts[:verPos]:
+				if ververify(x):
+					pkgcache[mypkg]=None
+					return None
+					#names can't have versiony looking parts
+			myval=["-".join(myparts[:verPos]),myparts[verPos],revision]
+			pkgcache[mypkg]=myval
+			return myval
+	else:
+		pkgcache[mypkg]=None
+		return None
+
+_valid_category = re.compile("^\w[\w-]*")
+
+catcache={}
+def catpkgsplit(mydata,silent=1):
+	"""
+	Takes a Category/Package-Version-Rev and returns a list of each.
+	
+	@param mydata: Data to split
+	@type mydata: string 
+	@param silent: suppress error messages
+	@type silent: Boolean (integer)
+	@rype: list
+	@return:
+	1.  If each exists, it returns [cat, pkgname, version, rev]
+	2.  If cat is not specificed in mydata, cat will be "null"
+	3.  if rev does not exist it will be '-r0'
+	4.  If cat is invalid (specified but has incorrect syntax)
+ 		an InvalidData Exception will be thrown
+	"""
+	
+	# Categories may contain a-zA-z0-9+_- but cannot start with -
+	global _valid_category
+	import portage_dep
+	try:
+		if not catcache[mydata]:
+			return None
+		return catcache[mydata][:]
+	except KeyError:
+		pass
+	mysplit=mydata.split("/")
+	p_split=None
+	if len(mysplit)==1:
+		retval=["null"]
+		p_split=pkgsplit(mydata,silent=silent)
+	elif len(mysplit)==2:
+		if portage_dep._dep_check_strict and \
+			not _valid_category.match(mysplit[0]):
+			raise InvalidData("Invalid category in %s" %mydata )
+		retval=[mysplit[0]]
+		p_split=pkgsplit(mysplit[1],silent=silent)
+	if not p_split:
+		catcache[mydata]=None
+		return None
+	retval.extend(p_split)
+	catcache[mydata]=retval
+	return retval
+
+def catsplit(mydep):
+        return mydep.split("/", 1)
+
+def best(mymatches):
+	"""Accepts None arguments; assumes matches are valid."""
+	if mymatches is None:
+		return ""
+	if not len(mymatches):
+		return ""
+	bestmatch = mymatches[0]
+	p2 = catpkgsplit(bestmatch)[1:]
+	for x in mymatches[1:]:
+		p1 = catpkgsplit(x)[1:]
+		if pkgcmp(p1, p2) > 0:
+			bestmatch = x
+			p2 = catpkgsplit(bestmatch)[1:]
+	return bestmatch
Index: /vendor/portage/current/pym/xpak.py
===================================================================
--- /vendor/portage/current/pym/xpak.py	(revision 3419)
+++ /vendor/portage/current/pym/xpak.py	(revision 3419)
@@ -0,0 +1,421 @@
+# Copyright 2001-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: xpak.py 5595 2007-01-12 08:08:03Z antarus $
+
+
+# The format for a tbz2/xpak:
+#
+#  tbz2: tar.bz2 + xpak + (xpak_offset) + "STOP"
+#  xpak: "XPAKPACK" + (index_len) + (data_len) + index + data + "XPAKSTOP"
+# index: (pathname_len) + pathname + (data_offset) + (data_len)
+#        index entries are concatenated end-to-end.
+#  data: concatenated data chunks, end-to-end.
+#
+# [tarball]XPAKPACKIIIIDDDD[index][data]XPAKSTOPOOOOSTOP
+#
+# (integer) == encodeint(integer)  ===> 4 characters (big-endian copy)
+# '+' means concatenate the fields ===> All chunks are strings
+
+import sys,os,shutil,errno
+from stat import *
+
+def addtolist(mylist,curdir):
+	"""(list, dir) --- Takes an array(list) and appends all files from dir down
+	the directory tree. Returns nothing. list is modified."""
+	for x in os.listdir("."):
+		if os.path.isdir(x):
+			os.chdir(x)
+			addtolist(mylist,curdir+x+"/")
+			os.chdir("..")
+		else:
+			if curdir+x not in mylist:
+				mylist.append(curdir+x)
+
+def encodeint(myint):
+	"""Takes a 4 byte integer and converts it into a string of 4 characters.
+	Returns the characters in a string."""
+	part1=chr((myint >> 24 ) & 0x000000ff)
+	part2=chr((myint >> 16 ) & 0x000000ff)
+	part3=chr((myint >> 8 ) & 0x000000ff)
+	part4=chr(myint & 0x000000ff)
+	return part1+part2+part3+part4
+
+def decodeint(mystring):
+	"""Takes a 4 byte string and converts it into a 4 byte integer.
+	Returns an integer."""
+	myint=0
+	myint=myint+ord(mystring[3])
+	myint=myint+(ord(mystring[2]) << 8)
+	myint=myint+(ord(mystring[1]) << 16)
+	myint=myint+(ord(mystring[0]) << 24)
+	return myint
+
+def xpak(rootdir,outfile=None):
+	"""(rootdir,outfile) -- creates an xpak segment of the directory 'rootdir'
+	and under the name 'outfile' if it is specified. Otherwise it returns the
+	xpak segment."""
+	try:
+		origdir=os.getcwd()
+	except SystemExit, e:
+		raise
+	except:
+		os.chdir("/")
+		origdir="/"
+	os.chdir(rootdir)
+	mylist=[]
+
+	addtolist(mylist,"")
+	mylist.sort()
+	mydata = {}
+	for x in mylist:
+		a = open(x, "r")
+		mydata[x] = a.read()
+		a.close()
+	os.chdir(origdir)
+
+	xpak_segment = xpak_mem(mydata)
+	if outfile:
+		outf = open(outfile, "w")
+		outf.write(xpak_segment)
+		outf.close()
+	else:
+		return xpak_segment
+
+def xpak_mem(mydata):
+	"""Create an xpack segement from a map object."""
+	indexglob=""
+	indexpos=0
+	dataglob=""
+	datapos=0
+	for x, newglob in mydata.iteritems():
+		mydatasize=len(newglob)
+		indexglob=indexglob+encodeint(len(x))+x+encodeint(datapos)+encodeint(mydatasize)
+		indexpos=indexpos+4+len(x)+4+4
+		dataglob=dataglob+newglob
+		datapos=datapos+mydatasize
+	return "XPAKPACK" \
+	+ encodeint(len(indexglob)) \
+	+ encodeint(len(dataglob)) \
+	+ indexglob \
+	+ dataglob \
+	+ "XPAKSTOP"
+
+def xsplit(infile):
+	"""(infile) -- Splits the infile into two files.
+	'infile.index' contains the index segment.
+	'infile.dat' contails the data segment."""
+	myfile=open(infile,"r")
+	mydat=myfile.read()
+	myfile.close()
+	
+	splits = xsplit_mem(mydat)
+	if not splits:
+		return False
+	
+	myfile=open(infile+".index","w")
+	myfile.write(splits[0])
+	myfile.close()
+	myfile=open(infile+".dat","w")
+	myfile.write(splits[1])
+	myfile.close()
+	return True
+
+def xsplit_mem(mydat):
+	if mydat[0:8]!="XPAKPACK":
+		return None
+	if mydat[-8:]!="XPAKSTOP":
+		return None
+	indexsize=decodeint(mydat[8:12])
+	datasize=decodeint(mydat[12:16])
+	return (mydat[16:indexsize+16], mydat[indexsize+16:-8])
+
+def getindex(infile):
+	"""(infile) -- grabs the index segment from the infile and returns it."""
+	myfile=open(infile,"r")
+	myheader=myfile.read(16)
+	if myheader[0:8]!="XPAKPACK":
+		myfile.close()
+		return
+	indexsize=decodeint(myheader[8:12])
+	myindex=myfile.read(indexsize)
+	myfile.close()
+	return myindex
+
+def getboth(infile):
+	"""(infile) -- grabs the index and data segments from the infile.
+	Returns an array [indexSegment,dataSegment]"""
+	myfile=open(infile,"r")
+	myheader=myfile.read(16)
+	if myheader[0:8]!="XPAKPACK":
+		myfile.close()
+		return
+	indexsize=decodeint(myheader[8:12])
+	datasize=decodeint(myheader[12:16])
+	myindex=myfile.read(indexsize)
+	mydata=myfile.read(datasize)
+	myfile.close()
+	return myindex, mydata
+
+def listindex(myindex):
+	"""Print to the terminal the filenames listed in the indexglob passed in."""
+	for x in getindex_mem(myindex):
+		print x
+
+def getindex_mem(myindex):
+	"""Returns the filenames listed in the indexglob passed in."""
+	myindexlen=len(myindex)
+	startpos=0
+	myret=[]
+	while ((startpos+8)<myindexlen):
+		mytestlen=decodeint(myindex[startpos:startpos+4])
+		myret=myret+[myindex[startpos+4:startpos+4+mytestlen]]
+		startpos=startpos+mytestlen+12
+	return myret
+
+def searchindex(myindex,myitem):
+	"""(index,item) -- Finds the offset and length of the file 'item' in the
+	datasegment via the index 'index' provided."""
+	mylen=len(myitem)
+	myindexlen=len(myindex)
+	startpos=0
+	while ((startpos+8)<myindexlen):
+		mytestlen=decodeint(myindex[startpos:startpos+4])
+		if mytestlen==mylen:
+			if myitem==myindex[startpos+4:startpos+4+mytestlen]:
+				#found
+				datapos=decodeint(myindex[startpos+4+mytestlen:startpos+8+mytestlen]);
+				datalen=decodeint(myindex[startpos+8+mytestlen:startpos+12+mytestlen]);
+				return datapos, datalen
+		startpos=startpos+mytestlen+12
+		
+def getitem(myid,myitem):
+	myindex=myid[0]
+	mydata=myid[1]
+	myloc=searchindex(myindex,myitem)
+	if not myloc:
+		return None
+	return mydata[myloc[0]:myloc[0]+myloc[1]]
+
+def xpand(myid,mydest):
+	myindex=myid[0]
+	mydata=myid[1]
+	try:
+		origdir=os.getcwd()
+	except SystemExit, e:
+		raise
+	except:
+		os.chdir("/")
+		origdir="/"
+	os.chdir(mydest)
+	myindexlen=len(myindex)
+	startpos=0
+	while ((startpos+8)<myindexlen):
+		namelen=decodeint(myindex[startpos:startpos+4])
+		datapos=decodeint(myindex[startpos+4+namelen:startpos+8+namelen]);
+		datalen=decodeint(myindex[startpos+8+namelen:startpos+12+namelen]);
+		myname=myindex[startpos+4:startpos+4+namelen]
+		dirname=os.path.dirname(myname)
+		if dirname:
+			if not os.path.exists(dirname):
+				os.makedirs(dirname)
+		mydat=open(myname,"w")
+		mydat.write(mydata[datapos:datapos+datalen])
+		mydat.close()
+		startpos=startpos+namelen+12
+	os.chdir(origdir)
+
+class tbz2:
+	def __init__(self,myfile):
+		self.file=myfile
+		self.filestat=None
+		self.index=""
+		self.infosize=0
+		self.xpaksize=0
+		self.indexsize=None
+		self.datasize=None
+		self.indexpos=None
+		self.datapos=None
+		self.scan()
+
+	def decompose(self,datadir,cleanup=1):
+		"""Alias for unpackinfo() --- Complement to recompose() but optionally
+		deletes the destination directory. Extracts the xpak from the tbz2 into
+		the directory provided. Raises IOError if scan() fails.
+		Returns result of upackinfo()."""
+		if not self.scan():
+			raise IOError
+		if cleanup:
+			self.cleanup(datadir)
+		if not os.path.exists(datadir):
+			os.makedirs(datadir)
+		return self.unpackinfo(datadir)
+	def compose(self,datadir,cleanup=0):
+		"""Alias for recompose()."""
+		return recompose(datadir,cleanup)
+	def recompose(self,datadir,cleanup=0):
+		"""Creates an xpak segment from the datadir provided, truncates the tbz2
+		to the end of regular data if an xpak segment already exists, and adds
+		the new segment to the file with terminating info."""
+		xpdata = xpak(datadir)
+		self.recompose_mem(xpdata)
+		if cleanup:
+			self.cleanup(datadir)
+
+	def recompose_mem(self, xpdata):
+		self.scan() # Don't care about condition... We'll rewrite the data anyway.
+		myfile=open(self.file,"a+")
+		if not myfile:
+			raise IOError
+		myfile.seek(-self.xpaksize,2) # 0,2 or -0,2 just mean EOF.
+		myfile.truncate()
+		myfile.write(xpdata+encodeint(len(xpdata))+"STOP")
+		myfile.flush()
+		myfile.close()
+		return 1
+
+	def cleanup(self, datadir):
+		datadir_split = os.path.split(datadir)
+		if len(datadir_split) >= 2 and len(datadir_split[1]) > 0:
+			# This is potentially dangerous,
+			# thus the above sanity check.
+			try:
+				shutil.rmtree(datadir)
+			except OSError, oe:
+				if oe.errno == errno.ENOENT:
+					pass
+				else:
+					raise oe
+
+	def scan(self):
+		"""Scans the tbz2 to locate the xpak segment and setup internal values.
+		This function is called by relevant functions already."""
+		try:
+			mystat=os.stat(self.file)
+			if self.filestat:
+				changed=0
+				for x in [ST_SIZE, ST_MTIME, ST_CTIME]:
+					if mystat[x] != self.filestat[x]:
+						changed=1
+				if not changed:
+					return 1
+			self.filestat=mystat
+			a=open(self.file,"r")
+			a.seek(-16,2)
+			trailer=a.read()
+			self.infosize=0
+			self.xpaksize=0
+			if trailer[-4:]!="STOP":
+				a.close()
+				return 0
+			if trailer[0:8]!="XPAKSTOP":
+				a.close()
+				return 0
+			self.infosize=decodeint(trailer[8:12])
+			self.xpaksize=self.infosize+8
+			a.seek(-(self.xpaksize),2)
+			header=a.read(16)
+			if header[0:8]!="XPAKPACK":
+				a.close()
+				return 0
+			self.indexsize=decodeint(header[8:12])
+			self.datasize=decodeint(header[12:16])
+			self.indexpos=a.tell()
+			self.index=a.read(self.indexsize)
+			self.datapos=a.tell()
+			a.close()
+			return 2
+		except SystemExit, e:
+			raise
+		except:
+			return 0
+
+	def filelist(self):
+		"""Return an array of each file listed in the index."""
+		if not self.scan():
+			return None
+		return getindex_mem(self.index)
+
+	def getfile(self,myfile,mydefault=None):
+		"""Finds 'myfile' in the data segment and returns it."""
+		if not self.scan():
+			return None
+		myresult=searchindex(self.index,myfile)
+		if not myresult:
+			return mydefault
+		a=open(self.file,"r")
+		a.seek(self.datapos+myresult[0],0)
+		myreturn=a.read(myresult[1])
+		a.close()
+		return myreturn
+
+	def getelements(self,myfile):
+		"""A split/array representation of tbz2.getfile()"""
+		mydat=self.getfile(myfile)
+		if not mydat:
+			return []
+		return mydat.split()
+
+	def unpackinfo(self,mydest):
+		"""Unpacks all the files from the dataSegment into 'mydest'."""
+		if not self.scan():
+			return 0
+		try:
+			origdir=os.getcwd()
+		except SystemExit, e:
+			raise
+		except:
+			os.chdir("/")
+			origdir="/"
+		a=open(self.file,"r")
+		if not os.path.exists(mydest):
+			os.makedirs(mydest)
+		os.chdir(mydest)
+		startpos=0
+		while ((startpos+8)<self.indexsize):
+			namelen=decodeint(self.index[startpos:startpos+4])
+			datapos=decodeint(self.index[startpos+4+namelen:startpos+8+namelen]);
+			datalen=decodeint(self.index[startpos+8+namelen:startpos+12+namelen]);
+			myname=self.index[startpos+4:startpos+4+namelen]
+			dirname=os.path.dirname(myname)
+			if dirname:
+				if not os.path.exists(dirname):
+					os.makedirs(dirname)
+			mydat=open(myname,"w")
+			a.seek(self.datapos+datapos)
+			mydat.write(a.read(datalen))
+			mydat.close()
+			startpos=startpos+namelen+12
+		a.close()
+		os.chdir(origdir)
+		return 1
+
+	def get_data(self):
+		"""Returns all the files from the dataSegment as a map object."""
+		if not self.scan():
+			return 0
+		a = open(self.file, "r")
+		mydata = {}
+		startpos=0
+		while ((startpos+8)<self.indexsize):
+			namelen=decodeint(self.index[startpos:startpos+4])
+			datapos=decodeint(self.index[startpos+4+namelen:startpos+8+namelen]);
+			datalen=decodeint(self.index[startpos+8+namelen:startpos+12+namelen]);
+			myname=self.index[startpos+4:startpos+4+namelen]
+			a.seek(self.datapos+datapos)
+			mydata[myname] = a.read(datalen)
+			startpos=startpos+namelen+12
+		a.close()
+		return mydata
+
+	def getboth(self):
+		"""Returns an array [indexSegment,dataSegment]"""
+		if not self.scan():
+			return None
+
+		a = open(self.file,"r")
+		a.seek(self.datapos)
+		mydata =a.read(self.datasize)
+		a.close()
+
+		return self.index, mydata
+
Index: /vendor/portage/current/src/bsd-flags/PKG-INFO
===================================================================
--- /vendor/portage/current/src/bsd-flags/PKG-INFO	(revision 3419)
+++ /vendor/portage/current/src/bsd-flags/PKG-INFO	(revision 3419)
@@ -0,0 +1,10 @@
+Metadata-Version: 1.0
+Name: bsd-chflags
+Version: 0.1
+Summary: UNKNOWN
+Home-page: UNKNOWN
+Author: Stephen Bennett
+Author-email: spb@gentoo.org
+License: UNKNOWN
+Description: UNKNOWN
+Platform: UNKNOWN
Index: /vendor/portage/current/src/bsd-flags/chflags.c
===================================================================
--- /vendor/portage/current/src/bsd-flags/chflags.c	(revision 3419)
+++ /vendor/portage/current/src/bsd-flags/chflags.c	(revision 3419)
@@ -0,0 +1,161 @@
+/* $Id: chflags.c 3483 2006-06-10 21:40:40Z genone $ */
+
+#include "Python.h"
+
+#include <sys/stat.h>
+
+static char chflags_lchflags__doc__[];
+static PyObject * chflags_lchflags(PyObject *self, PyObject *args);
+static char chflags_lgetflags__doc__[];
+static PyObject * chflags_lgetflags(PyObject *self, PyObject *args);
+static char chflags_lhasproblems__doc__[];
+static PyObject * chflags_lhasproblems(PyObject *self, PyObject *args);
+
+static char chflags__doc__[] = "Provide some operations for manipulating" \
+	"FreeBSD's filesystem flags";
+
+static PyMethodDef chflags_methods[] = {
+	{"lchflags", chflags_lchflags, METH_VARARGS, chflags_lchflags__doc__},
+	{"lgetflags", chflags_lgetflags, METH_VARARGS, chflags_lgetflags__doc__},
+	{"lhasproblems", chflags_lhasproblems, METH_VARARGS, chflags_lhasproblems__doc__},
+	{NULL, NULL}
+};
+
+static char chflags_lchflags__doc__[] = 
+"lchflags(path, flags) -> None\n\
+Change the flags on path to equal flags.";
+
+static char chflags_lgetflags__doc__[] =
+"lgetflags(path) -> Integer\n\
+Returns the file flags on path.";
+
+static char chflags_lhasproblems__doc__[] = 
+"lhasproblems(path) -> Integer\n\
+Returns 1 if path has any flags set that prevent write operations;\n\
+0 otherwise.";
+
+static const unsigned long problemflags=0x00160016;
+
+#if defined __FreeBSD__
+static PyObject *chflags_lchflags(PyObject *self, PyObject *args) 
+{
+	char *path = NULL;
+	int flags;
+	int res;
+
+	if (!PyArg_ParseTuple(args, "eti:lchflags",
+			      Py_FileSystemDefaultEncoding, &path,
+			      &flags))
+	{
+		return NULL;
+	}
+
+	res = lchflags(path, flags);
+
+	PyMem_Free(path);
+	return PyInt_FromLong((long)res);
+}
+
+static PyObject *chflags_lhasproblems(PyObject *self, PyObject *args)
+{
+	char *path = NULL;
+	struct stat sb;
+	int res;
+
+	if (!PyArg_ParseTuple(args, "et:lhasproblems",
+				Py_FileSystemDefaultEncoding, &path))
+	{
+		return NULL;
+	}
+
+	res = lstat(path, &sb);
+
+	PyMem_Free(path);
+		
+	if (res < 0)
+	{
+		return PyInt_FromLong((long)res);
+	}
+
+	if (sb.st_flags & problemflags)
+		return PyInt_FromLong(1);
+	else
+		return PyInt_FromLong(0);
+}
+
+static PyObject *chflags_lgetflags(PyObject *self, PyObject *args)
+{
+	char *path = NULL;
+	struct stat sb;
+	int res;
+
+	if (!PyArg_ParseTuple(args, "et:lgetflags",
+			      Py_FileSystemDefaultEncoding, &path))
+	{
+		return NULL;
+	}
+
+	res = lstat(path, &sb);
+
+	if (res < 0)
+	{
+		PyMem_Free(path);
+		return PyInt_FromLong((long)res);
+	}
+
+	PyMem_Free(path);
+
+	return PyInt_FromLong((long)sb.st_flags);
+}
+
+#else
+#warning Not on FreeBSD; building dummy lchflags
+
+static PyObject *chflags_lgetflags(PyObject *self, PyObject *args)
+{
+	/* Obviously we can't set flags if the OS/filesystem doesn't support them. */
+	return PyInt_FromLong(0);
+}
+
+static PyObject *chflags_lchflags(PyObject *self, PyObject *args)
+{
+	/* If file system flags aren't supported, just return 0,
+	 as the effect is basically the same. */
+	return PyInt_FromLong(0);
+}
+
+static PyObject *chflags_lhasproblems(PyObject *self, PyObject *args)
+{
+	return PyInt_FromLong(0);
+}
+
+#endif
+
+static int ins(PyObject *m, char *symbolname, int value)
+{
+	return PyModule_AddIntConstant(m, symbolname, value);
+}
+
+DL_EXPORT(void) initchflags(void)
+{
+	PyObject *m;
+	m = Py_InitModule4("chflags", chflags_methods, chflags__doc__,
+			   (PyObject*)NULL, PYTHON_API_VERSION);
+	
+	ins(m, "UF_SETTABLE",  0x0000ffff);
+	ins(m, "UF_NODUMP",    0x00000001);
+	ins(m, "UF_IMMUTABLE", 0x00000002);
+	ins(m, "UF_APPEND",    0x00000004);
+	ins(m, "UF_OPAQUE",    0x00000008);
+	ins(m, "UF_NOUNLINK",  0x00000010);
+
+	ins(m, "SF_SETTABLE",  0xffff0000);
+	ins(m, "SF_NODUMP",    0x00010000);
+	ins(m, "SF_IMMUTABLE", 0x00020000);
+	ins(m, "SF_APPEND",    0x00040000);
+	ins(m, "SF_OPAQUE",    0x00080000);
+	ins(m, "SF_NOUNLINK",  0x00100000);
+	ins(m, "SF_SNAPSHOT",  0x00200000);
+
+	ins(m, "PROBLEM_FLAGS", 0x00160016);
+}
Index: /vendor/portage/current/src/bsd-flags/setup.cfg
===================================================================
--- /vendor/portage/current/src/bsd-flags/setup.cfg	(revision 3419)
+++ /vendor/portage/current/src/bsd-flags/setup.cfg	(revision 3419)
@@ -0,0 +1,6 @@
+# bsd-flags
+# $Id: setup.cfg 3483 2006-06-10 21:40:40Z genone $
+
+[bdist_rpm]
+release = 1
+python=python2
Index: /vendor/portage/current/src/bsd-flags/setup.py
===================================================================
--- /vendor/portage/current/src/bsd-flags/setup.py	(revision 3419)
+++ /vendor/portage/current/src/bsd-flags/setup.py	(revision 3419)
@@ -0,0 +1,24 @@
+#! /usr/bin/env python
+# $Id: setup.py 3483 2006-06-10 21:40:40Z genone $
+
+from os import chdir, stat
+from distutils.core import setup, Extension
+
+setup (# Distribution meta-data
+        name = "bsd-chflags",
+        version = "0.1",
+        description = "",
+        author = "Stephen Bennett",
+        author_email = "spb@gentoo.org",
+       	license = "",
+        long_description = \
+         '''''',
+        ext_modules = [ Extension(
+                            "chflags",
+                            ["chflags.c"],
+                            libraries=[],
+                        ) 
+                      ],
+        url = "",
+      )
+
Index: /vendor/portage/current/src/python-missingos/ChangeLog
===================================================================
--- /vendor/portage/current/src/python-missingos/ChangeLog	(revision 3419)
+++ /vendor/portage/current/src/python-missingos/ChangeLog	(revision 3419)
@@ -0,0 +1,16 @@
+# $Id: ChangeLog 3483 2006-06-10 21:40:40Z genone $
+
+python-missingos ChangeLog
+Jonathon D Nelson <jnelson@gentoo.org>
+2 April 2002
+
+ 2 April 2002 14:15 jnelson
+  * Add optional 'mode' parameter to mknod
+  * Change from missingosmodule to missingos.
+  * Add some __doc__ entries
+  * Remove stupid hack for Python 1.5.2 support,
+    1.5.2 doesn't have Py_FileSystemDefaultEncoding anyway.
+  * Return description of error when mode not p,b,c,u in mknod
+
+ 2 April 2002 12:10 jnelson
+  * Populate files
Index: /vendor/portage/current/src/python-missingos/PKG-INFO
===================================================================
--- /vendor/portage/current/src/python-missingos/PKG-INFO	(revision 3419)
+++ /vendor/portage/current/src/python-missingos/PKG-INFO	(revision 3419)
@@ -0,0 +1,10 @@
+Metadata-Version: 1.0
+Name: python-missingos
+Version: 0.2
+Summary: UNKNOWN
+Home-page: UNKNOWN
+Author: Jonathon D Nelson
+Author-email: jnelson@gentoo.org
+License: UNKNOWN
+Description: UNKNOWN
+Platform: UNKNOWN
Index: /vendor/portage/current/src/python-missingos/README
===================================================================
--- /vendor/portage/current/src/python-missingos/README	(revision 3419)
+++ /vendor/portage/current/src/python-missingos/README	(revision 3419)
@@ -0,0 +1,15 @@
+# $Id: README 3483 2006-06-10 21:40:40Z genone $
+
+python-missingos
+Jonathon D Nelson <jnelson@gentoo.org>
+2 April 2002
+
+INTRO
+=====
+This module provides some missing file operations that don't
+seem to be provided by the standard os and posix modules.
+This list currently includes lchown and mknod.
+
+COPYRIGHT
+=========
+GPL
Index: /vendor/portage/current/src/python-missingos/missingos.c
===================================================================
--- /vendor/portage/current/src/python-missingos/missingos.c	(revision 3419)
+++ /vendor/portage/current/src/python-missingos/missingos.c	(revision 3419)
@@ -0,0 +1,120 @@
+/* $Id: missingos.c 3483 2006-06-10 21:40:40Z genone $ */
+
+#include "Python.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+static char missingos_lchown__doc__[];
+static PyObject * missingos_lchown(PyObject *self, PyObject *args);
+static char missingos_mknod__doc__[];
+static PyObject * missingos_mknod(PyObject *self, PyObject *args);
+
+static char missingos__doc__[] = "Provide some operations that\
+    are missing from the standard os / posix modules.";
+
+static PyMethodDef missingos_methods[] = {
+    {"lchown", missingos_lchown, METH_VARARGS, missingos_lchown__doc__},
+    {"mknod", missingos_mknod, METH_VARARGS, missingos_mknod__doc__},
+    {NULL,		NULL}		/* sentinel */
+};
+
+static PyObject *
+posix_error_with_allocated_filename(char* name)
+{
+    PyObject *rc = PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
+    PyMem_Free(name);
+    return rc;
+}
+
+static char missingos_lchown__doc__[] =
+"lchown(path, uid, gid) -> None\n\
+Change the owner and group id of path to the numeric uid and gid.";
+
+static PyObject *
+missingos_lchown(PyObject *self, PyObject *args) {
+    char *path = NULL;
+    int uid, gid;
+    int res;
+    if (!PyArg_ParseTuple(args, "etii:lchown",
+                          Py_FileSystemDefaultEncoding, &path,
+                          &uid, &gid))
+        return NULL;
+    res = lchown(path, (uid_t) uid, (gid_t) gid);
+    if (res < 0)
+        return posix_error_with_allocated_filename(path);
+    PyMem_Free(path);
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static char missingos_mknod__doc__[] =
+"mknod(path, type, major, minor [, mode=0600 ]) -> None\n\
+Create a special file. Mode fixed at 0600.\
+Note that for type 'p' major and minor are ignored.\
+";
+
+static PyObject *
+missingos_mknod(PyObject *self, PyObject *args) {
+    char *path = NULL;
+    char *type = NULL;
+    int major = 0;
+    int minor = 0;
+    mode_t real_mode;
+    dev_t real_dev;
+    int mode = 0600;
+
+    int res;
+    if (!PyArg_ParseTuple(args, "etsii|i:mknod",
+                          Py_FileSystemDefaultEncoding, &path,
+                          &type, &major, &minor, &mode))
+        return NULL;
+    /* type can be *one* of b, c, u, p */
+    /* major/minor are forbidden for p, reqd otherwise */
+    if (!strcmp(type, "p")) {
+        /* pipe */
+        if (major != 0 || minor != 0) {
+            return NULL;
+        }
+        real_mode = S_IFIFO;
+        major = 0;
+        minor = 0;
+    } else if (!strcmp(type, "b")) {
+        /* block */
+        real_mode = S_IFBLK;
+    } else if (!strcmp(type, "c")) {
+        real_mode = S_IFCHR;
+        /* char */
+    } else if (!strcmp(type, "u")) {
+        real_mode = S_IFCHR;
+        /* unbuffered char */
+    } else {
+        /* error */
+        PyErr_SetString(PyExc_ValueError, "type must be one of p,b,c,u");
+        return NULL;
+    }
+
+    real_mode |= mode;
+    real_dev = (major << 8) | minor;
+
+    /* use mode to modify real_mode */
+
+    res = mknod(path, real_mode, real_dev);
+    if (res < 0)
+        return posix_error_with_allocated_filename(path);
+    PyMem_Free(path);
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+
+DL_EXPORT(void)
+initmissingos(void) {
+    PyObject *m;
+
+    m = Py_InitModule4("missingos", missingos_methods,
+                       missingos__doc__, (PyObject *)NULL,
+                       PYTHON_API_VERSION);
+}
Index: /vendor/portage/current/src/python-missingos/setup.cfg
===================================================================
--- /vendor/portage/current/src/python-missingos/setup.cfg	(revision 3419)
+++ /vendor/portage/current/src/python-missingos/setup.cfg	(revision 3419)
@@ -0,0 +1,8 @@
+# python-missingos
+# $Id: setup.cfg 3483 2006-06-10 21:40:40Z genone $
+
+[bdist_rpm]
+release = 1
+doc_files = ChangeLog
+            README
+python=python2
Index: /vendor/portage/current/src/python-missingos/setup.py
===================================================================
--- /vendor/portage/current/src/python-missingos/setup.py	(revision 3419)
+++ /vendor/portage/current/src/python-missingos/setup.py	(revision 3419)
@@ -0,0 +1,24 @@
+#!/usr/bin/python
+# $Id: setup.py 3483 2006-06-10 21:40:40Z genone $
+
+from os import chdir, stat
+from distutils.core import setup, Extension
+
+setup (# Distribution meta-data
+        name = "python-missingos",
+        version = "0.2",
+        description = "",
+        author = "Jonathon D Nelson",
+        author_email = "jnelson@gentoo.org",
+       	license = "",
+        long_description = \
+         '''''',
+        ext_modules = [ Extension(
+                            "missingos",
+                            ["missingos.c"],
+                            libraries=[],
+                        ) 
+                      ],
+        url = "",
+      )
+
Index: /vendor/portage/current/src/tbz2tool.c
===================================================================
--- /vendor/portage/current/src/tbz2tool.c	(revision 3419)
+++ /vendor/portage/current/src/tbz2tool.c	(revision 3419)
@@ -0,0 +1,228 @@
+/* $Id: tbz2tool.c 3483 2006-06-10 21:40:40Z genone $ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+/*buffered reading/writing size*/
+#define BUFLEN 262144 
+char *myname="tbz2tool";
+struct stat *mystat=NULL;
+void *mybuf;
+FILE *datafile, *dbfile, *outfile, *infile;
+unsigned char endbuf[8];
+long seekto,insize;
+
+int exists(const char *myfile) {
+	int result;
+	result=stat(myfile,mystat);
+	if (result==-1)
+		return 0;
+	return 1;
+}
+
+void writefile(FILE *src, FILE *dest) {
+	int count=1;
+	while (count) {
+		count=fread(mybuf, 1, BUFLEN, src);
+		fwrite(mybuf, 1, count, dest);
+	}
+}
+
+void writefileto(FILE *src, FILE *dest, int endpos) {
+	int pos=ftell(src);
+	int thiscount;
+	while (pos < endpos) {
+		/* thiscount=how much to read */
+		thiscount=endpos-pos;
+		if (thiscount>BUFLEN)
+			thiscount=BUFLEN;
+		thiscount=fread(mybuf, 1, thiscount , src);
+		/* thiscount=how much we actually did read */
+		if (thiscount==0)
+			/* eof -- shouldn't happen */
+			break;
+		/* update internal position counter */
+		pos+=thiscount;
+		fwrite(mybuf, 1, thiscount, dest);
+	}
+}
+
+int main(int argc, char **argv) {
+	if ((argc==2) && (!(strcmp(argv[1],"--help"))))
+		goto usage;
+	if (argc!=5) {
+		printf("%s: four arguments expected\n",myname);
+		goto error;
+	}
+	if (!(mystat=(struct stat *) malloc(sizeof(struct stat))))
+		goto memalloc;
+		
+	if (!(mybuf=(void *) malloc(BUFLEN))) {
+		free(mystat);
+		goto memalloc;
+	}
+	
+	/* JOIN MODE */
+	if (!(strcmp(argv[1],"join"))) {
+	
+		/* check if datafile exists */
+		if (!(exists(argv[2]))) {
+			printf("%s: %s doesn't exist\n",myname,argv[2]);
+			free(mystat);
+			goto error;
+		}
+		
+		/* check if dbfile exists */
+		if (!(exists(argv[3]))) {
+			printf("%s: %s doesn't exist\n",myname,argv[3]);
+			free(mystat);
+			goto error;
+		}
+		/* create end buffer for later use */
+		endbuf[0]=((mystat->st_size) & 0xff000000) >> 24;
+		endbuf[1]=((mystat->st_size) & 0x00ff0000) >> 16;
+		endbuf[2]=((mystat->st_size) & 0x0000ff00) >> 8;
+		endbuf[3]=(mystat->st_size) & 0x000000ff;
+		endbuf[4]='S';
+		endbuf[5]='T';
+		endbuf[6]='O';
+		endbuf[7]='P';
+	
+		/* if outfile exists, unlink first (safer) */
+		if (exists(argv[4])) 
+			unlink(argv[4]);
+		
+		/* open datafile for reading */
+		if ((datafile=fopen(argv[2],"r"))==NULL) {
+			free(mybuf);
+			free(mystat);
+			printf("%s: Error opening %s\n",myname,argv[2]);
+			goto error;
+		}
+		
+		/* open dbfile for reading */
+		if ((dbfile=fopen(argv[3],"r"))==NULL) {
+			fclose(datafile);
+			free(mybuf);
+			free(mystat);
+			printf("%s: Error opening %s\n",myname,argv[3]);
+			goto error;
+		}
+	
+		/* open outfile for writing */
+		if ((outfile=fopen(argv[4],"a"))==NULL) {
+			fclose(dbfile);
+			fclose(datafile);
+			free(mybuf);
+			free(mystat);
+			printf("%s: Error opening %s\n",myname,argv[4]);
+			goto error;
+		}
+	
+		writefile(datafile,outfile);
+		writefile(dbfile,outfile);
+		fwrite(endbuf,1,8,outfile);
+		fclose(outfile);
+		fclose(dbfile);
+		fclose(datafile);
+		free(mybuf);
+		free(mystat);
+		exit(0);	
+	
+	/* SPLIT MODE */
+	} else if (!(strcmp(argv[1],"split"))) {
+	
+		/* check if infile exists */
+		if (!(exists(argv[2]))) {
+			printf("%s: %s doesn't exist\n",myname,argv[2]);
+			free(mystat);
+			goto error;
+		}
+		
+		/* store infile size for later use */
+
+		insize=mystat->st_size;
+		
+		/* if datafile exists, unlink first (safer) */
+		if (exists(argv[3])) 
+			unlink(argv[3]);
+		
+		/* if dbfile exists, unlink first (safer) */
+		if (exists(argv[4])) 
+			unlink(argv[4]);
+	
+		/* open infile for reading */
+		if ((infile=fopen(argv[2],"r"))==NULL) {
+			free(mybuf);
+			free(mystat);
+			printf("%s: Error opening %s\n",myname,argv[2]);
+			goto error;
+		}
+		
+		/* read in end buffer */
+		fseek(infile,-8,SEEK_END);	
+		fread(endbuf,1,8,infile);
+		/* quick end buffer read and verification */
+		if ( (endbuf[4]!='S') || (endbuf[5]!='T') || (endbuf[6]!='O') || (endbuf[7]!='P') )	{
+			fclose(infile);
+			free(mybuf);
+			free(mystat);
+			printf("%s: %s appears to be corrupt (end buffer invalid)\n",myname,argv[2]);
+			goto error;
+		}
+		
+		seekto=0;
+		seekto=seekto+endbuf[0]*256*256*256;
+		seekto=seekto+endbuf[1]*256*256;
+		seekto=seekto+endbuf[2]*256;
+		seekto=seekto+endbuf[3];
+		
+		/* open datafile for writing */
+		if ((datafile=fopen(argv[3],"a"))==NULL) {
+			fclose(infile);
+			free(mybuf);
+			free(mystat);
+			printf("%s: Error opening %s\n",myname,argv[3]);
+			goto error;
+		}
+	
+		/* open dbfile for writing */
+		if ((dbfile=fopen(argv[4],"a"))==NULL) {
+			fclose(datafile);
+			fclose(infile);
+			free(mybuf);
+			free(mystat);
+			printf("%s: Error opening %s\n",myname,argv[4]);
+			goto error;
+		}
+
+		rewind(infile);
+		writefileto(infile,datafile,insize-(seekto+8));
+		fseek(infile,-(seekto+8),SEEK_END);
+		writefileto(infile,dbfile,insize-8);
+		fclose(infile);
+		fclose(dbfile);
+		fclose(datafile);
+		free(mybuf);
+		free(mystat);
+		exit(0);	
+		
+	} else {
+		free(mybuf);
+		free(mystat);
+		goto usage;
+	}
+	
+	usage:
+	printf("Usage: %s join DATAFILE DBFILE OUTFILE (datafile + dbfile -> outfile)\n       %s split INFILE DATAFILE DBFILE (infile -> datafile + dbfile)\n",myname,myname);
+error:
+	exit(1);
+memalloc:
+	printf("%s: memory allocation error\n",myname);
+	exit(2);
+}
Index: /vendor/portage/current/tests/__init__.py
===================================================================
--- /vendor/portage/current/tests/__init__.py	(revision 3419)
+++ /vendor/portage/current/tests/__init__.py	(revision 3419)
@@ -0,0 +1,49 @@
+# tests/__init__.py -- Portage Unit Test functionality
+# Copyright 2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: __init__.py 5541 2007-01-11 06:18:50Z zmedico $
+
+import os, unittest
+
+def main():
+	
+	testDirs = ["portage", "portage_util","portage_versions", "portage_dep"]
+
+	suite = unittest.TestSuite()
+
+	basedir = os.path.dirname(__file__)
+	for mydir in testDirs:
+		suite.addTests(getTests(os.path.join(basedir, mydir), basedir) )
+
+	return unittest.TextTestRunner(verbosity=2).run(suite)
+
+def my_import(name):
+	mod = __import__(name)
+	components = name.split('.')
+	for comp in components[1:]:
+		mod = getattr(mod, comp)
+	return mod
+
+def getTests( path, base_path ):
+	"""
+
+	path is the path to a given subdir ( 'portage/' for example)
+	This does a simple filter on files in that dir to give us modules
+	to import
+
+	"""
+	import os
+	files = os.listdir( path )
+	files = [ f[:-3] for f in files if f.startswith("test_") and f.endswith(".py") ]
+	parent_path = path[len(base_path)+1:]
+	parent_module = ".".join(("tests", parent_path))
+	result = []
+	for mymodule in files:
+		try:
+			# Make the trailing / a . for module importing
+			modname = ".".join((parent_module, mymodule))
+			mod = my_import(modname)
+			result.append( unittest.TestLoader().loadTestsFromModule(mod) )
+		except ImportError:
+			raise
+	return result
Index: /vendor/portage/current/tests/portage/__init__.py
===================================================================
--- /vendor/portage/current/tests/portage/__init__.py	(revision 3419)
+++ /vendor/portage/current/tests/portage/__init__.py	(revision 3419)
@@ -0,0 +1,4 @@
+# tests/portage/__init__.py -- Portage Unit Test functionality
+# Copyright 2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: __init__.py 5596 2007-01-12 08:08:53Z antarus $
Index: /vendor/portage/current/tests/portage_dep/__init__.py
===================================================================
--- /vendor/portage/current/tests/portage_dep/__init__.py	(revision 3419)
+++ /vendor/portage/current/tests/portage_dep/__init__.py	(revision 3419)
@@ -0,0 +1,4 @@
+# tests/portage/__init__.py -- Portage Unit Test functionality
+# Copyright 2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: __init__.py 5596 2007-01-12 08:08:53Z antarus $
Index: /vendor/portage/current/tests/portage_dep/test_dep_getcpv.py
===================================================================
--- /vendor/portage/current/tests/portage_dep/test_dep_getcpv.py	(revision 3419)
+++ /vendor/portage/current/tests/portage_dep/test_dep_getcpv.py	(revision 3419)
@@ -0,0 +1,31 @@
+# test_dep_getcpv.py -- Portage Unit Testing Functionality
+# Copyright 2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: test_dep_getcpv.py 5633 2007-01-13 19:25:20Z antarus $
+
+from unittest import TestCase
+from portage_dep import dep_getcpv
+
+class DepGetCPV(TestCase):
+	""" A simple testcase for isvalidatom
+	"""
+
+	def testDepGetCPV(self):
+		
+		prefix_ops = ["<", ">", "=", "~", "!", "<=", 
+			      ">=", "!=", "!<", "!>", "!~",""]
+
+		bad_prefix_ops = [ ">~", "<~", "~>", "~<" ]
+		postfix_ops = [ "*", "" ]
+
+		cpvs = ["sys-apps/portage"]
+
+		for cpv in cpvs:
+			for prefix in prefix_ops:
+				for postfix in postfix_ops:
+					self.assertEqual( dep_getcpv( 
+						prefix + cpv + postfix ), cpv )
+			for prefix in bad_prefix_ops:
+				for postfix in postfix_ops:
+					self.assertNotEqual( dep_getcpv(
+						prefix + cpv + postfix ), cpv )
Index: /vendor/portage/current/tests/portage_dep/test_dep_getslot.py
===================================================================
--- /vendor/portage/current/tests/portage_dep/test_dep_getslot.py	(revision 3419)
+++ /vendor/portage/current/tests/portage_dep/test_dep_getslot.py	(revision 3419)
@@ -0,0 +1,27 @@
+# test_dep_getslot.py -- Portage Unit Testing Functionality
+# Copyright 2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: test_dep_getslot.py 5633 2007-01-13 19:25:20Z antarus $
+
+from unittest import TestCase
+from portage_dep import dep_getslot
+
+class DepGetSlot(TestCase):
+	""" A simple testcase for isvalidatom
+	"""
+
+	def testDepGetSlot(self):
+
+		slot_char = ":"
+		slots = ( "a", "1.2", "1", "IloveVapier", None )
+		cpvs = ["sys-apps/portage"]
+
+		for cpv in cpvs:
+			for slot in slots:
+				if slot:
+					self.assertEqual( dep_getslot( 
+						cpv + slot_char + slot ), slot )
+				else:
+					self.assertEqual( dep_getslot( cpv ), slot )
+
+		self.assertEqual( dep_getslot( "sys-apps/portage:"), "" )
Index: /vendor/portage/current/tests/portage_dep/test_get_operator.py
===================================================================
--- /vendor/portage/current/tests/portage_dep/test_get_operator.py	(revision 3419)
+++ /vendor/portage/current/tests/portage_dep/test_get_operator.py	(revision 3419)
@@ -0,0 +1,26 @@
+# test_match_from_list.py -- Portage Unit Testing Functionality
+# Copyright 2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: test_get_operator.py 5596 2007-01-12 08:08:53Z antarus $
+
+from unittest import TestCase
+from portage_dep import get_operator
+
+class GetOperator(TestCase):
+
+	def testGetOperator(self):
+
+		# get_operator does not validate operators
+		tests = [ ( "~", "~" ), ( "=", "=" ), ( ">", ">" ),
+			  ( ">=", ">=" ), ( "<=", "<=" ) , ( "", None ),
+			  ( ">~", ">" ), ("~<", "~"), ( "=~", "=" ),
+			  ( "=>", "=" ), ("=<", "=") ]
+
+		testCP = "sys-apps/portage"
+
+		for test in tests:
+			result = get_operator( test[0] + testCP )
+			self.assertEqual( result, test[1] )
+
+		result = get_operator( "=sys-apps/portage*" )
+		self.assertEqual( result , "=*" )
Index: /vendor/portage/current/tests/portage_dep/test_isjustname.py
===================================================================
--- /vendor/portage/current/tests/portage_dep/test_isjustname.py	(revision 3419)
+++ /vendor/portage/current/tests/portage_dep/test_isjustname.py	(revision 3419)
@@ -0,0 +1,25 @@
+# test_isjustname.py -- Portage Unit Testing Functionality
+# Copyright 2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: test_isjustname.py 5633 2007-01-13 19:25:20Z antarus $
+
+from unittest import TestCase
+from portage_dep import isjustname
+
+class IsJustName(TestCase):
+
+	def testIsJustName(self):
+
+		cats = ( "", "sys-apps/", "foo/", "virtual/" )
+		pkgs = ( "portage", "paludis", "pkgcore", "notARealPkg" )
+		vers = ( "", "-2.0-r3", "-1.0_pre2", "-3.1b" )
+
+		for pkg in pkgs:
+			for cat in cats:
+				for ver in vers:
+					if len(ver):
+						self.assertFalse( isjustname( cat + pkg + ver ),
+						msg="isjustname(%s) is True!" % (cat + pkg + ver) )
+					else:
+						self.assertTrue( isjustname( cat + pkg + ver ),
+						msg="isjustname(%s) is False!" % (cat + pkg + ver) )
Index: /vendor/portage/current/tests/portage_dep/test_isvalidatom.py
===================================================================
--- /vendor/portage/current/tests/portage_dep/test_isvalidatom.py	(revision 3419)
+++ /vendor/portage/current/tests/portage_dep/test_isvalidatom.py	(revision 3419)
@@ -0,0 +1,38 @@
+# test_isvalidatom.py -- Portage Unit Testing Functionality
+# Copyright 2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: test_isvalidatom.py 5633 2007-01-13 19:25:20Z antarus $
+
+from unittest import TestCase
+from portage_dep import isvalidatom
+import portage_dep
+portage_dep._dep_check_strict = True
+
+class IsValidAtom(TestCase):
+	""" A simple testcase for isvalidatom
+	"""
+
+	def testIsValidAtom(self):
+		
+		tests = [ ( "sys-apps/portage", True ),
+			  ( "=sys-apps/portage-2.1", True ),
+		 	  ( "=sys-apps/portage-2.1*", True ),
+			  ( ">=sys-apps/portage-2.1", True ),
+			  ( "<=sys-apps/portage-2.1", True ),
+			  ( ">sys-apps/portage-2.1", True ),
+			  ( "<sys-apps/portage-2.1", True ),
+			  ( "~sys-apps/portage-2.1", True ),
+			  ( ">~cate-gory/foo-1.0", False ),
+			  ( ">~category/foo-1.0", False ),
+			  ( "<~category/foo-1.0", False ),
+			  ( "###cat/foo-1.0", False ),
+			  ( "~sys-apps/portage", False ),
+			  ( "portage", False ) ]
+
+		for test in tests:
+			if test[1]:
+				atom_type = "valid"
+			else:
+				atom_type = "invalid"
+			self.assertEqual( bool(isvalidatom( test[0] )), test[1],
+				msg="isvalidatom(%s) != %s" % ( test[0], test[1] ) )
Index: /vendor/portage/current/tests/portage_dep/test_match_from_list.py
===================================================================
--- /vendor/portage/current/tests/portage_dep/test_match_from_list.py	(revision 3419)
+++ /vendor/portage/current/tests/portage_dep/test_match_from_list.py	(revision 3419)
@@ -0,0 +1,31 @@
+# test_match_from_list.py -- Portage Unit Testing Functionality
+# Copyright 2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: test_match_from_list.py 5596 2007-01-12 08:08:53Z antarus $
+
+from unittest import TestCase
+from portage_dep import match_from_list
+
+class AtomCmpEqualGlob(TestCase):
+        """ A simple testcase for =* glob matching
+        """
+
+        def testEqualGlobPass(self):
+                tests = [ ("=sys-apps/portage-45*", "sys-apps/portage-045" ),
+                          ("=sys-fs/udev-1*", "sys-fs/udev-123"),
+                          ("=sys-fs/udev-4*", "sys-fs/udev-456" ) ]
+
+# I need to look up the cvs syntax
+#                         ("=sys-fs/udev_cvs*","sys-fs/udev_cvs_pre4" ) ]
+
+                for test in tests:
+                        self.assertEqual( len(match_from_list( test[0], [test[1]] )), 1 )
+
+        def testEqualGlobFail(self):
+                tests = [ ("=sys-apps/portage-2*", "sys-apps/portage-2.1" ),
+                          ("=sys-apps/portage-2.1*", "sys-apps/portage-2.1.2" ) ]
+                for test in tests:
+                        try:
+                                self.assertEqual( len( match_from_list( test[0], [test[1]] ) ), 1 )
+                        except TypeError: # failure is ok here
+                                pass
Index: /vendor/portage/current/tests/portage_util/__init__.py
===================================================================
--- /vendor/portage/current/tests/portage_util/__init__.py	(revision 3419)
+++ /vendor/portage/current/tests/portage_util/__init__.py	(revision 3419)
@@ -0,0 +1,5 @@
+# tests/portage_util/__init__.py -- Portage Unit Test functionality
+# Copyright 2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: __init__.py 5596 2007-01-12 08:08:53Z antarus $
+
Index: /vendor/portage/current/tests/portage_util/test_grabdict.py
===================================================================
--- /vendor/portage/current/tests/portage_util/test_grabdict.py	(revision 3419)
+++ /vendor/portage/current/tests/portage_util/test_grabdict.py	(revision 3419)
@@ -0,0 +1,12 @@
+# test_grabDict.py -- Portage Unit Testing Functionality
+# Copyright 2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: test_grabdict.py 5596 2007-01-12 08:08:53Z antarus $
+
+from unittest import TestCase, TestLoader
+from portage_util import grabdict
+
+class GrabDictTestCase(TestCase):
+	
+	def testGrabDictPass(self):
+		pass
Index: /vendor/portage/current/tests/portage_util/test_normalizedPath.py
===================================================================
--- /vendor/portage/current/tests/portage_util/test_normalizedPath.py	(revision 3419)
+++ /vendor/portage/current/tests/portage_util/test_normalizedPath.py	(revision 3419)
@@ -0,0 +1,15 @@
+# test_normalizePath.py -- Portage Unit Testing Functionality
+# Copyright 2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: test_normalizedPath.py 5596 2007-01-12 08:08:53Z antarus $
+
+from unittest import TestCase
+
+class NormalizePathTestCase(TestCase):
+	
+	def testNormalizePath(self):
+		
+		from portage_util import normalize_path
+		path = "///foo/bar/baz"
+		good = "/foo/bar/baz"
+		self.assertEqual(normalize_path(path), good)
Index: /vendor/portage/current/tests/portage_util/test_stackDictList.py
===================================================================
--- /vendor/portage/current/tests/portage_util/test_stackDictList.py	(revision 3419)
+++ /vendor/portage/current/tests/portage_util/test_stackDictList.py	(revision 3419)
@@ -0,0 +1,18 @@
+# test_stackDictList.py -- Portage Unit Testing Functionality
+# Copyright 2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: test_stackDictList.py 5596 2007-01-12 08:08:53Z antarus $
+
+from unittest import TestCase
+
+class StackDictListTestCase(TestCase):
+
+	def testStackDictList(self):
+		from portage_util import stack_dictlist
+		
+		tests = [ ({'a':'b'},{'x':'y'},False,{'a':['b'],'x':['y']}) ]
+		tests.append(( {'KEYWORDS':['alpha','x86']},{'KEYWORDS':['-*']},True,{} ))
+		tests.append(( {'KEYWORDS':['alpha','x86']},{'KEYWORDS':['-x86']},True,{'KEYWORDS':['alpha']} ))
+		for test in tests:
+			self.assertEqual(
+			stack_dictlist([test[0],test[1]],incremental=test[2]), test[3] )
Index: /vendor/portage/current/tests/portage_util/test_stackDicts.py
===================================================================
--- /vendor/portage/current/tests/portage_util/test_stackDicts.py	(revision 3419)
+++ /vendor/portage/current/tests/portage_util/test_stackDicts.py	(revision 3419)
@@ -0,0 +1,37 @@
+# test_stackDicts.py -- Portage Unit Testing Functionality
+# Copyright 2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: test_stackDicts.py 5596 2007-01-12 08:08:53Z antarus $
+
+from unittest import TestCase
+from portage_util import stack_dicts
+
+
+class StackDictsTestCase(TestCase):
+	
+	def testStackDictsPass(self):
+		
+		tests = [ ( [ { "a":"b" }, { "b":"c" } ], { "a":"b", "b":"c" },
+			  False, [], False ),
+			  ( [ { "a":"b" }, { "a":"c" } ], { "a":"b c" },
+			  True, [], False ),
+			  ( [ { "a":"b" }, { "a":"c" } ], { "a":"b c" },
+			  False, ["a"], False ),
+			  ( [ { "a":"b" }, None ], { "a":"b" },
+			  False, [], True ),
+			  ( [ None ], None, False, [], False ),
+			  ( [ None, {}], {}, False, [], True ) ]
+
+
+		for test in tests:
+			result = stack_dicts( test[0], test[2], test[3], test[4] )
+			self.assertEqual( result, test[1] )
+	
+	def testStackDictsFail(self):
+		
+		tests = [ ( [ None, {} ], None, False, [], True ),
+			  ( [ { "a":"b"}, {"a":"c" } ], { "a":"b c" },
+				False, [], False ) ]
+		for test in tests:
+			result = stack_dicts( test[0], test[2], test[3], test[4] )
+			self.assertNotEqual( result , test[1] )
Index: /vendor/portage/current/tests/portage_util/test_stackLists.py
===================================================================
--- /vendor/portage/current/tests/portage_util/test_stackLists.py	(revision 3419)
+++ /vendor/portage/current/tests/portage_util/test_stackLists.py	(revision 3419)
@@ -0,0 +1,20 @@
+# test_stackLists.py -- Portage Unit Testing Functionality
+# Copyright 2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: test_stackLists.py 5596 2007-01-12 08:08:53Z antarus $
+
+from unittest import TestCase
+from portage_util import stack_lists
+
+class StackListsTestCase(TestCase):
+	
+	def testStackLists(self):
+		
+		tests = [ ( [ ['a','b','c'], ['d','e','f'] ], ['a','c','b','e','d','f'], False ),
+			  ( [ ['a','x'], ['b','x'] ], ['a','x','b'], False ),
+			  ( [ ['a','b','c'], ['-*'] ], [], True ),
+			  ( [ ['a'], ['-a'] ], [], True ) ]
+
+		for test in tests:
+			result = stack_lists( test[0], test[2] )
+			self.assertEqual( result , test[1] )
Index: /vendor/portage/current/tests/portage_util/test_uniqueArray.py
===================================================================
--- /vendor/portage/current/tests/portage_util/test_uniqueArray.py	(revision 3419)
+++ /vendor/portage/current/tests/portage_util/test_uniqueArray.py	(revision 3419)
@@ -0,0 +1,26 @@
+# test_uniqueArray.py -- Portage Unit Testing Functionality
+# Copyright 2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: test_uniqueArray.py 5596 2007-01-12 08:08:53Z antarus $
+
+from unittest import TestCase
+from portage_util import unique_array
+
+class UniqueArrayTestCase(TestCase):
+	
+	def testUniqueArrayPass(self):
+		"""
+		test portage_util.uniqueArray()
+		"""
+
+		import os
+
+		tests = [ ( ["a","a","a",os,os,[],[],[]], ['a',os,[]] ), 
+			  ( [1,1,1,2,3,4,4] , [1,2,3,4]) ]
+
+		for test in tests:
+			result = unique_array( test[0] )
+			for item in test[1]:
+				number = result.count(item)
+				self.failIf( number is not 1, msg="%s contains %s of %s, \
+					should be only 1" % (result, number, item) )
Index: /vendor/portage/current/tests/portage_util/test_varExpand.py
===================================================================
--- /vendor/portage/current/tests/portage_util/test_varExpand.py	(revision 3419)
+++ /vendor/portage/current/tests/portage_util/test_varExpand.py	(revision 3419)
@@ -0,0 +1,60 @@
+# test_varExpand.py -- Portage Unit Testing Functionality
+# Copyright 2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: test_varExpand.py 5596 2007-01-12 08:08:53Z antarus $
+
+from unittest import TestCase, TestLoader
+from portage_util import varexpand
+
+class VarExpandTestCase(TestCase):
+	
+	def testVarExpandPass(self):
+
+		varDict = { "a":"5", "b":"7", "c":"-5" }
+		for key in varDict.keys():
+			result = varexpand( "$%s" % key, varDict )
+			
+			self.failIf( result != varDict[key],
+				msg="Got %s != %s, from varexpand( %s, %s )" % \
+					( result, varDict[key], "$%s" % key, varDict ) )
+			result = varexpand( "${%s}" % key, varDict )
+			self.failIf( result != varDict[key],
+				msg="Got %s != %s, from varexpand( %s, %s )" % \
+					( result, varDict[key], "${%s}" % key, varDict ) )
+
+	def testVarExpandDoubleQuotes(self):
+		
+		varDict = { "a":"5" }
+		tests = [ ("\"${a}\"", "5") ]
+		for test in tests:
+			result = varexpand( test[0], varDict )
+			self.failIf( result != test[1],
+				msg="Got %s != %s from varexpand( %s, %s )" \
+				% ( result, test[1], test[0], varDict ) )
+
+	def testVarExpandSingleQuotes(self):
+		
+		varDict = { "a":"5" }
+		tests = [ ("\'${a}\'", "${a}") ]
+		for test in tests:
+			result = varexpand( test[0], varDict )
+			self.failIf( result != test[1],
+				msg="Got %s != %s from varexpand( %s, %s )" \
+				% ( result, test[1], test[0], varDict ) )
+
+	def testVarExpandFail(self):
+
+		varDict = { "a":"5", "b":"7", "c":"15" }
+
+		testVars = [ "fail" ]
+
+		for var in testVars:
+			result = varexpand( "$%s" % var, varDict )
+			self.failIf( len(result),
+				msg="Got %s == %s, from varexpand( %s, %s )" \
+					% ( result, var, "$%s" % var, varDict ) )
+
+			result = varexpand( "${%s}" % var, varDict )
+			self.failIf( len(result),
+				msg="Got %s == %s, from varexpand( %s, %s )" \
+					% ( result, var, "${%s}" % var, varDict ) )
Index: /vendor/portage/current/tests/portage_versions/__init__.py
===================================================================
--- /vendor/portage/current/tests/portage_versions/__init__.py	(revision 3419)
+++ /vendor/portage/current/tests/portage_versions/__init__.py	(revision 3419)
@@ -0,0 +1,4 @@
+# tests/portage/__init__.py -- Portage Unit Test functionality
+# Copyright 2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: __init__.py 5596 2007-01-12 08:08:53Z antarus $
Index: /vendor/portage/current/tests/portage_versions/test_vercmp.py
===================================================================
--- /vendor/portage/current/tests/portage_versions/test_vercmp.py	(revision 3419)
+++ /vendor/portage/current/tests/portage_versions/test_vercmp.py	(revision 3419)
@@ -0,0 +1,40 @@
+# test_vercmp.py -- Portage Unit Testing Functionality
+# Copyright 2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: test_vercmp.py 5537 2007-01-11 05:09:38Z antarus $
+
+from unittest import TestCase
+from portage_versions import vercmp
+
+class VerCmpTestCase(TestCase):
+	""" A simple testCase for portage_versions.vercmp()
+	"""
+	
+	def testVerCmpGreater(self):
+		
+		tests = [ ( "6.0", "5.0"), ("5.0","5")]
+		for test in tests:
+			self.failIf( vercmp( test[0], test[1] ) <= 0, msg="%s < %s? Wrong!" % (test[0],test[1]) )
+
+	def testVerCmpLess(self):
+		"""
+		pre < alpha < beta < rc < p -> test each of these, they are inductive (or should be..)
+		"""
+		tests = [ ( "4.0", "5.0"), ("5", "5.0"), ("1.0_pre2","1.0_p2"),
+			("1.0_alpha2", "1.0_p2"),("1.0_alpha1", "1.0_beta1"),("1.0_beta3","1.0_rc3")]
+		for test in tests:
+			self.failIf( vercmp( test[0], test[1]) >= 0, msg="%s > %s? Wrong!" % (test[0],test[1]))
+	
+	
+	def testVerCmpEqual(self):
+		
+		tests = [ ("4.0", "4.0") ]
+		for test in tests:
+			self.failIf( vercmp( test[0], test[1]) != 0, msg="%s != %s? Wrong!" % (test[0],test[1]))
+			
+	def testVerNotEqual(self):
+		
+		tests = [ ("1","2"),("1.0_alpha","1.0_pre"),("1.0_beta","1.0_alpha"),
+			("0", "0.0")]
+		for test in tests:
+			self.failIf( vercmp( test[0], test[1]) == 0, msg="%s == %s? Wrong!" % (test[0],test[1]))
Index: /vendor/portage/current/tests/runTests
===================================================================
--- /vendor/portage/current/tests/runTests	(revision 3419)
+++ /vendor/portage/current/tests/runTests	(revision 3419)
@@ -0,0 +1,22 @@
+#!/usr/bin/python
+# runTests.py -- Portage Unit Test Functionality
+# Copyright 2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id: runTests 5533 2007-01-10 21:13:43Z zmedico $
+
+
+import os, sys
+import os.path as osp
+
+# Insert our parent dir so we can do shiny import "tests"
+# This line courtesy of Marienz and Pkgcore ;)
+sys.path.insert(0, osp.dirname(osp.dirname(osp.abspath(__file__))))
+
+# Grab SVN portage files instead of normal ones.
+sys.path.insert(0, os.path.join(sys.path[0], "pym"))
+
+import tests
+if __name__ == "__main__":
+	result = tests.main()
+	if result.failures:
+		sys.exit(1)
