commit:     ad67685714c348aad22a3819b4d0326822a49425
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Thu Dec  6 12:55:51 2018 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Thu Dec  6 12:57:27 2018 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=ad676857

Squashed commit of the following due to GCO sign-off sever check:

commit c9cd57da216f21de49f8a57a4a692f8116d27ead
Author: Zac Medico <zmedico <AT> gentoo.org>
Date:   Tue Aug 7 21:04:19 2018 -0700

    Updates for portage-2.3.45 release

commit 807ac3d9d6eecead73f59d399b30559e5c731587
Author: Michael Orlitzky <mjo <AT> gentoo.org>
Date:   Tue Aug 7 12:46:04 2018 -0400

    bin/install-qa-check.d: add new 90bad-bin-group-write QA check.

    System executables that are writable by a non-root user pose a
    security risk. Anyone who can write to an executable can change its
    behavior. If that executable is later run with elevated privileges
    (say, by root, when the machine starts), then the non-root user can
    escalate his own privileges to those of the person running the
    modified executable.

    The 90bad-bin-owner check already addresses one cause for a non-root
    user to be able to modify an executable: because he owns it. This
    commit adds another check, to ensure that no non-root *groups* have
    write access to any system executables. On a "normal" system, all
    system executables should be writable only by the super-user's group,
    if any. To avoid false-positives, non-"normal" systems (like prefix)
    are skipped.

    Closes: https://bugs.gentoo.org/629398

commit 04e71a831bc42f2a0de1694dd2013eac0414e007
Author: Michael Orlitzky <mjo <AT> gentoo.org>
Date:   Tue Aug 7 12:46:03 2018 -0400

    bin/install-qa-check.d: add new 90bad-bin-owner QA check.

    System executables that are not owned by root pose a security
    risk. The owner of the executable is free to modify it at any time;
    so, for example, he can change a daemon's behavior to make it
    malicious before the next time the service is started (usually by
    root).

    On a "normal" system, the superuser should own every system executable
    (even setuid ones, for security reasons). This commit adds a new
    install-time check that reports any such binaries with a QA
    warning. To avoid false positives, non-"normal" systems (like prefix)
    are skipped at the moment.

    Bug: https://bugs.gentoo.org/629398

commit eb81c8081ae53e862f9f0f82c6119f936ca896e7
Author: Zac Medico <zmedico <AT> gentoo.org>
Date:   Tue Aug 7 11:29:51 2018 -0700

    action_metadata: refresh eclass cache (bug 663022)

    After sync, the eclass cache can contain stale data, therefore
    use the update_eclasses method to refresh it.

    Bug: https://bugs.gentoo.org/663022

commit 3f462e983b2e08107e0f7e4a2753d8deca4ac62a
Author: Zac Medico <zmedico <AT> gentoo.org>
Date:   Mon Aug 6 16:38:55 2018 -0700

    Refer to "ebuild repository" rather than "portage tree"

commit 78c52aa79707756d3b816fdbfa9004f7b9dcac41
Author: Zac Medico <zmedico <AT> gentoo.org>
Date:   Mon Aug 6 11:42:29 2018 -0700

    repoman: remove obsolete herds checks

commit 6b4252d3a0f12808a5bcce888b7f68e1f84b5301
Author: Zac Medico <zmedico <AT> gentoo.org>
Date:   Sat Jul 28 14:22:42 2018 -0700

    Add asyncio.create_subprocess_exec support for python2 (bug 662388)

    The asyncio.create_subprocess_exec function is essential for
    using subprocesses in coroutines, so add support to do this
    for python2. This paves the way for extensive use of coroutines
    in portage, since coroutines are well-suited for many portage
    tasks that involve subprocesses.

    Bug: https://bugs.gentoo.org/662388

commit f391b2cc5384fc38e99a0598cb3de2346e297c25
Author: Zac Medico <zmedico <AT> gentoo.org>
Date:   Sat Aug 4 13:18:47 2018 -0700

    compression_probe: decompress zstd --long=31 (bug 634980)

    In order to decompress files compressed with zstd --long=31, add
    --long=31 to the zstd decompress options. Even though zstd compression
    does not support --long=31 on 32-bit platforms, decompression with
    --long=31 still works as long as the file was compressed with a
    smaller windowLog.

    Reported-by: Martin Väth <martin <AT> mvath.de>
    Bug: https://bugs.gentoo.org/634980

commit 12aa832c91a6f2c2faee5a2e839b7f1ed5a0ee6e
Author: Francesco Turco <fturco <AT> fastmail.fm>
Date:   Sat Aug 4 20:47:40 2018 +0200

    install-qa-check.d: fix hardened <AT> g.o e-mail address

    Closes: https://github.com/gentoo/portage/pull/350

Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>

 README                                             |   4 +-
 RELEASE-NOTES                                      |  11 ++
 bin/ebuild                                         |   2 +-
 bin/ebuild.sh                                      |   2 +-
 bin/install-qa-check.d/10executable-issues         |   2 +-
 bin/install-qa-check.d/90bad-bin-group-write       |  55 ++++++
 bin/install-qa-check.d/90bad-bin-owner             |  48 ++++++
 cnf/make.conf.example                              |   8 +-
 lib/_emerge/actions.py                             |   2 +-
 lib/_emerge/create_world_atom.py                   |   2 +-
 lib/_emerge/depgraph.py                            |   2 +-
 lib/_emerge/search.py                              |   2 +-
 lib/portage/__init__.py                            |   2 +-
 lib/portage/_global_updates.py                     |   2 +-
 lib/portage/dbapi/porttree.py                      |   2 +-
 lib/portage/dbapi/vartree.py                       |   2 +-
 lib/portage/emaint/modules/merges/merges.py        |   2 +-
 lib/portage/metadata.py                            |   6 +-
 lib/portage/news.py                                |   2 +-
 lib/portage/package/ebuild/config.py               |   2 +-
 lib/portage/sync/modules/rsync/rsync.py            |   2 +-
 .../util/futures/asyncio/test_subprocess_exec.py   | 184 ++++++---------------
 lib/portage/util/compression_probe.py              |   2 +-
 lib/portage/util/futures/_asyncio/__init__.py      |  53 ++++++
 lib/portage/util/futures/_asyncio/process.py       | 107 ++++++++++++
 lib/portage/util/futures/_asyncio/streams.py       |  96 +++++++++++
 lib/portage/util/futures/compat_coroutine.py       |   6 +-
 man/emerge.1                                       |  10 +-
 man/make.conf.5                                    |   2 +-
 man/portage.5                                      |   6 +-
 repoman/README                                     |   2 +-
 repoman/lib/repoman/__init__.py                    |   2 +-
 repoman/lib/repoman/checks/herds/__init__.py       |   0
 repoman/lib/repoman/checks/herds/herdbase.py       | 135 ---------------
 repoman/lib/repoman/checks/herds/metadata.py       |  26 ---
 repoman/lib/repoman/utilities.py                   |   2 +-
 repoman/man/repoman.1                              |   2 +-
 setup.py                                           |   2 +-
 38 files changed, 469 insertions(+), 330 deletions(-)

diff --git a/README b/README
index db660f3b8..4ab10c6b5 100644
--- a/README
+++ b/README
@@ -12,8 +12,8 @@ About Portage
 
 Portage is a package management system based on ports collections. The
 Package Manager Specification Project (PMS) standardises and documents
-the behaviour of Portage so that the Portage tree can be used by other
-package managers.
+the behaviour of Portage so that ebuild repositories can be used by
+other package managers.
 
 
 Dependencies

diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index b03d0ae3f..bda514fdb 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -1,6 +1,17 @@
 Release Notes; upgrade information mainly.
 Features/major bugfixes are listed in NEWS
 
+portage-2.3.45
+==================================
+* Bug Fixes:
+    - Bug 373209 FEATURES=test/USE=test mapping via USE_ORDER
+    - Bug 629398 QA Notice for executables writable by non-root user
+    - Bug 634980 zstd --long=31 binary package decompression support
+    - Bug 662388 asyncio.create_subprocess_exec support for python2
+    - Bug 662668 emerge --keep-going AttributeError
+    - Bug 663022 FileNotFoundError with FEATURES=metadata-transfer
+
+
 portage-2.3.44
 ==================================
 * Bug Fixes:

diff --git a/bin/ebuild b/bin/ebuild
index b87f2a1d7..f54bf3ce5 100755
--- a/bin/ebuild
+++ b/bin/ebuild
@@ -143,7 +143,7 @@ if not os.path.isabs(ebuild):
                mycwd = portage.normalize_path(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
+# portdbapi uses the canonical path for the base of the ebuild repository, but
 # subdirectories of the base can be built from symlinks (like crossdev does).
 ebuild_portdir = os.path.realpath(
        os.path.dirname(os.path.dirname(os.path.dirname(ebuild))))

diff --git a/bin/ebuild.sh b/bin/ebuild.sh
index f76a48d8e..e3c84150e 100755
--- a/bin/ebuild.sh
+++ b/bin/ebuild.sh
@@ -279,7 +279,7 @@ inherit() {
                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. 
It's
+                       # in comparison to the eclasses from the ebuild 
repository. It's
                        # disabled for nofetch, since that can be called by 
repoman and
                        # that triggers bug #407449 due to repoman not exporting
                        # non-essential variables such as INHERITED.

diff --git a/bin/install-qa-check.d/10executable-issues 
b/bin/install-qa-check.d/10executable-issues
index 8a2c8e875..6b33d281d 100644
--- a/bin/install-qa-check.d/10executable-issues
+++ b/bin/install-qa-check.d/10executable-issues
@@ -128,7 +128,7 @@ elf_check() {
                eqawarn
                eqawarn " Please include the following list of files in your 
report:"
                eqawarn " Note: Bugs should be filed for the respective 
maintainers"
-               eqawarn " of the package in question and not [email protected]."
+               eqawarn " of the package in question and not 
[email protected]."
                eqawarn "${f}"
                __vecho -ne '\n'
                die_msg="${die_msg} execstacks"

diff --git a/bin/install-qa-check.d/90bad-bin-group-write 
b/bin/install-qa-check.d/90bad-bin-group-write
new file mode 100644
index 000000000..786dde712
--- /dev/null
+++ b/bin/install-qa-check.d/90bad-bin-group-write
@@ -0,0 +1,55 @@
+# Copyright 1999-2018 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+bad_bin_group_write_check() {
+       # Warn about globally-installed executables (in /bin, /usr/bin, /sbin,
+       # /usr/sbin, or /opt/bin) that are group-writable by a nonzero GID.
+
+       # This check doesn't work on non-root prefix installations at
+       # the moment, because every executable therein is owned by a
+       # nonzero GID.
+       [[ "${EUID}" -ne "0" || "${PORTAGE_INST_UID}" -ne "0" ]] && return
+
+       local d f found=()
+
+       for d in "${ED%/}/opt/bin" "${ED%/}/bin"  "${ED%/}/usr/bin" \
+                                                          "${ED%/}/sbin" 
"${ED%/}/usr/sbin"; do
+               [[ -d "${d}" ]] || continue
+
+               # Read the results of the "find" command into the "found" array.
+               #
+               # Use -L to catch symlinks whose targets are vulnerable,
+               # even though it won't catch ABSOLUTE symlinks until the package
+               # is RE-installed (the first time around, the target won't 
exist).
+               #
+               # We match the GID and not the name "root" here because (for
+               # example) on FreeBSD, the superuser group is "wheel".
+               #
+               # We don't make an exception for setguid executables here, 
because
+               # a group-writable setguid executable is likely a mistake. By
+               # altering the contents of the executable, a member of the group
+               # can allow everyone (i.e. the people running it) to obtain the
+               # full privileges available to that group. While only existing
+               # group members can make that choice, it's a decision usually
+               # limited to the system administrator.
+               while read -r -d '' f; do
+                       found+=( "${f}" )
+               done < <(find -L "${d}"   \
+                                       -maxdepth 1   \
+                                       -type f       \
+                                       -perm /g+w    \
+                                       ! -gid 0      \
+                                       -print0)
+       done
+
+       if [[ ${found[@]} ]]; then
+               eqawarn "system executables group-writable by nonzero gid:"
+               for f in "${found[@]}"; do
+                       # Strip off the leading destdir before outputting the 
path.
+                       eqawarn "  ${f#${D%/}}"
+               done
+       fi
+}
+
+bad_bin_group_write_check
+:

diff --git a/bin/install-qa-check.d/90bad-bin-owner 
b/bin/install-qa-check.d/90bad-bin-owner
new file mode 100644
index 000000000..c3ee30746
--- /dev/null
+++ b/bin/install-qa-check.d/90bad-bin-owner
@@ -0,0 +1,48 @@
+# Copyright 1999-2018 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+bad_bin_owner_check() {
+       # Warn about globally-installed executables (in /bin, /usr/bin, /sbin,
+       # /usr/sbin, or /opt/bin) that are owned by a nonzero UID.
+
+       # This check doesn't work on non-root prefix installations at
+       # the moment, because every executable therein is owned by a
+       # nonzero UID.
+       [[ "${EUID}" -ne "0" || "${PORTAGE_INST_UID}" -ne "0" ]] && return
+
+       local d f found=()
+
+       for d in "${ED%/}/opt/bin" "${ED%/}/bin"  "${ED%/}/usr/bin" \
+                                                          "${ED%/}/sbin" 
"${ED%/}/usr/sbin"; do
+               [[ -d "${d}" ]] || continue
+
+               # Read the results of the "find" command into the "found" bash 
array.
+               #
+               # Use -L to catch symlinks whose targets are owned by a 
non-root user,
+               # even though it won't catch ABSOLUTE symlinks until the package
+               # is RE-installed (the first time around, the target won't 
exist).
+               #
+               # We do want to list non-superuser setuid executables, because
+               # they can be exploited. The owner can simply wipe the setuid
+               # bit, and then alter the contents of the file. The superuser
+               # will then have a time bomb in his $PATH.
+               while read -r -d '' f; do
+                       found+=( "${f}" )
+               done < <(find -L "${d}"   \
+                                       -maxdepth 1   \
+                                       -type f       \
+                                       ! -uid 0      \
+                                       -print0)
+       done
+
+       if [[ ${found[@]} ]]; then
+               eqawarn "system executables owned by nonzero uid:"
+               for f in "${found[@]}"; do
+                       # Strip off the leading destdir before outputting the 
path.
+                       eqawarn "  ${f#${D%/}}"
+               done
+       fi
+}
+
+bad_bin_owner_check
+:

diff --git a/cnf/make.conf.example b/cnf/make.conf.example
index 6de7a903f..ad290c7e6 100644
--- a/cnf/make.conf.example
+++ b/cnf/make.conf.example
@@ -13,7 +13,7 @@
 # very extensive set of USE variables described in our USE variable HOWTO at
 # https://wiki.gentoo.org/wiki/Handbook:X86/Working/USE
 #
-# The available list of use flags with descriptions is in your portage tree.
+# The available list of use flags with descriptions is in the ebuild 
repository.
 # Use 'less' to view them:  --> less /usr/portage/profiles/use.desc <--
 #
 # 'ufed' is an ncurses/dialog interface available in portage to make handling
@@ -102,7 +102,7 @@
 #     the application being installed.
 #PORTAGE_TMPDIR=@PORTAGE_EPREFIX@/var/tmp
 #
-# PORTDIR is the location of the portage tree. This is the repository
+# PORTDIR is the location of the ebuild repository. This is the repository
 #     for all profile information as well as all ebuilds. If you change
 #     this, you must update your /etc/portage/make.profile symlink accordingly.
 #     ***Warning***
@@ -193,7 +193,7 @@
 # Synchronizing Portage
 # =====================
 #
-# Each of these settings affects how Gentoo synchronizes your Portage tree.
+# Each of these settings affects how Gentoo synchronizes the ebuild repository.
 # Synchronization is handled by rsync and these settings allow some control
 # over how it is done.
 #
@@ -224,7 +224,7 @@
 #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
+#     a current ebuild repository before it exits with an error. This allows
 #     for a more successful retrieval without user intervention most times.
 #     If set to a negative number, then retry until all possible addresses are
 #     exhausted.

diff --git a/lib/_emerge/actions.py b/lib/_emerge/actions.py
index a9856de94..b2410065e 100644
--- a/lib/_emerge/actions.py
+++ b/lib/_emerge/actions.py
@@ -986,7 +986,7 @@ def calc_depclean(settings, trees, ldpath_mtimes,
                        msg.append("")
                        msg.extend(textwrap.wrap(
                                "Also, note that it may be necessary to 
manually uninstall " + \
-                               "packages that no longer exist in the portage 
tree, since " + \
+                               "packages that no longer exist in the 
repository, since " + \
                                "it may not be possible to satisfy their 
dependencies.", 65
                        ))
                        if action == "prune":

diff --git a/lib/_emerge/create_world_atom.py b/lib/_emerge/create_world_atom.py
index 947f8088a..c5e1f58be 100644
--- a/lib/_emerge/create_world_atom.py
+++ b/lib/_emerge/create_world_atom.py
@@ -67,7 +67,7 @@ def create_world_atom(pkg, args_set, root_config, 
before_install=False):
                #    unknown value, so just record an unslotted atom.
                #
                # 2) SLOT comes from an installed package and there is no
-               #    matching SLOT in the portage tree.
+               #    matching SLOT in the ebuild repository.
                #
                # Make sure that the slot atom is available in either the
                # portdb or the vardb, since otherwise the user certainly

diff --git a/lib/_emerge/depgraph.py b/lib/_emerge/depgraph.py
index cb8afa903..44d3eff6c 100644
--- a/lib/_emerge/depgraph.py
+++ b/lib/_emerge/depgraph.py
@@ -4007,7 +4007,7 @@ class depgraph(object):
                                pkgdir = os.path.dirname(ebuild_path)
                                tree_root = 
os.path.dirname(os.path.dirname(pkgdir))
                                cp = pkgdir[len(tree_root)+1:]
-                               error_msg = ("\n\n!!! '%s' is not in a valid 
portage tree "
+                               error_msg = ("\n\n!!! '%s' is not in a valid 
ebuild repository "
                                        "hierarchy or does not exist\n") % x
                                if not portage.isvalidatom(cp):
                                        writemsg(error_msg, noiselevel=-1)

diff --git a/lib/_emerge/search.py b/lib/_emerge/search.py
index eb52b2ca3..be639dfa3 100644
--- a/lib/_emerge/search.py
+++ b/lib/_emerge/search.py
@@ -104,7 +104,7 @@ class search(object):
                for db in self._dbs:
                        if db is not self._portdb:
                                # We don't want findname to return anything
-                               # unless it's an ebuild in a portage tree.
+                               # unless it's an ebuild in a repository.
                                # Otherwise, it's already built and we don't
                                # care about it.
                                continue

diff --git a/lib/portage/__init__.py b/lib/portage/__init__.py
index f9cc1a87c..db9c3854d 100644
--- a/lib/portage/__init__.py
+++ b/lib/portage/__init__.py
@@ -134,7 +134,7 @@ except ImportError as e:
        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("!!! ebuild repository 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")

diff --git a/lib/portage/_global_updates.py b/lib/portage/_global_updates.py
index 81ee484ee..6a595da56 100644
--- a/lib/portage/_global_updates.py
+++ b/lib/portage/_global_updates.py
@@ -22,7 +22,7 @@ def _global_updates(trees, prev_mtimes, quiet=False, 
if_mtime_changed=True):
        This simply returns if ROOT != "/" (when len(trees) != 1). If ROOT != 
"/"
        then the user should instead use emaint --fix movebin and/or moveinst.
 
-       @param trees: A dictionary containing portage trees.
+       @param trees: A dictionary containing package databases.
        @type trees: dict
        @param prev_mtimes: A dictionary containing mtimes of files located in
                $PORTDIR/profiles/updates/.

diff --git a/lib/portage/dbapi/porttree.py b/lib/portage/dbapi/porttree.py
index 677452273..aa8b50a57 100644
--- a/lib/portage/dbapi/porttree.py
+++ b/lib/portage/dbapi/porttree.py
@@ -239,7 +239,7 @@ class portdbapi(dbapi):
                # This is used as sanity check for aux_get(). If there is no
                # root eclass dir, we assume that PORTDIR is invalid or
                # missing. This check allows aux_get() to detect a missing
-               # portage tree and return early by raising a KeyError.
+               # repository and return early by raising a KeyError.
                self._have_root_eclass_dir = os.path.isdir(
                        
os.path.join(self.settings.repositories.mainRepoLocation(), "eclass"))
 

diff --git a/lib/portage/dbapi/vartree.py b/lib/portage/dbapi/vartree.py
index 943ba4ff8..645e8e313 100644
--- a/lib/portage/dbapi/vartree.py
+++ b/lib/portage/dbapi/vartree.py
@@ -2189,7 +2189,7 @@ class dblink(object):
                                                        "removal phases to 
execute successfully. "
                                                        "The ebuild will be "
                                                        "sourced and the 
eclasses "
-                                                       "from the current 
portage tree will be used "
+                                                       "from the current 
ebuild repository will be used "
                                                        "when necessary. 
Removal of "
                                                        "the ebuild file will 
cause the "
                                                        "pkg_prerm() and 
pkg_postrm() removal "

diff --git a/lib/portage/emaint/modules/merges/merges.py 
b/lib/portage/emaint/modules/merges/merges.py
index 416a725ff..e166150f4 100644
--- a/lib/portage/emaint/modules/merges/merges.py
+++ b/lib/portage/emaint/modules/merges/merges.py
@@ -182,7 +182,7 @@ class MergesHandler(object):
                                        % pkg_atom)
                        if not portdb.cpv_exists(pkg_name):
                                pkg_invalid_entries.add(
-                                       "'%s' does not exist in the portage 
tree." % pkg_name)
+                                       "'%s' does not exist in the ebuild 
repository." % pkg_name)
                        pkg_atoms.add(pkg_atom)
 
 

diff --git a/lib/portage/metadata.py b/lib/portage/metadata.py
index 1abec5a89..ffb7672d3 100644
--- a/lib/portage/metadata.py
+++ b/lib/portage/metadata.py
@@ -50,8 +50,10 @@ def action_metadata(settings, portdb, myopts, 
porttrees=None):
                        src_db = portdb._create_pregen_cache(path)
 
                if src_db is not None:
-                       porttrees_data.append(TreeData(portdb.auxdb[path],
-                               
portdb.repositories.get_repo_for_location(path).eclass_db, path, src_db))
+                       eclass_db = 
portdb.repositories.get_repo_for_location(path).eclass_db
+                       # Update eclass data which may be stale after sync.
+                       eclass_db.update_eclasses()
+                       porttrees_data.append(TreeData(portdb.auxdb[path], 
eclass_db, path, src_db))
 
        porttrees = [tree_data.path for tree_data in porttrees_data]
 

diff --git a/lib/portage/news.py b/lib/portage/news.py
index d4f1429b2..8397646b0 100644
--- a/lib/portage/news.py
+++ b/lib/portage/news.py
@@ -393,7 +393,7 @@ def count_unread_news(portdb, vardb, repos=None, 
update=True):
        By default, this will scan all repos and check for new items that have
        appeared since the last scan.
 
-       @param portdb: a portage tree database
+       @param portdb: an ebuild database
        @type portdb: pordbapi
        @param vardb: an installed package database
        @type vardb: vardbapi

diff --git a/lib/portage/package/ebuild/config.py 
b/lib/portage/package/ebuild/config.py
index 2eb766d0f..c00a51345 100644
--- a/lib/portage/package/ebuild/config.py
+++ b/lib/portage/package/ebuild/config.py
@@ -1130,7 +1130,7 @@ class config(object):
                archlist = self.archlist()
                if not archlist:
                        writemsg(_("--- 'profiles/arch.list' is empty or "
-                               "not available. Empty portage tree?\n"), 
noiselevel=1)
+                               "not available. Empty ebuild repository?\n"), 
noiselevel=1)
                else:
                        for group in groups:
                                if group not in archlist and \

diff --git a/lib/portage/sync/modules/rsync/rsync.py 
b/lib/portage/sync/modules/rsync/rsync.py
index 56e38631e..e0748794a 100644
--- a/lib/portage/sync/modules/rsync/rsync.py
+++ b/lib/portage/sync/modules/rsync/rsync.py
@@ -352,7 +352,7 @@ class RsyncSync(NewBase):
                                if (retries==0):
                                        if "--ask" in opts:
                                                uq = UserQuery(opts)
-                                               if uq.query("Do you want to 
sync your Portage tree " + \
+                                               if uq.query("Do you want to 
sync your ebuild repository " + \
                                                        "with the mirror at\n" 
+ blue(dosyncuri) + bold("?"),
                                                        enter_invalid) == "No":
                                                        print()

diff --git a/lib/portage/tests/util/futures/asyncio/test_subprocess_exec.py 
b/lib/portage/tests/util/futures/asyncio/test_subprocess_exec.py
index 5a812ba6a..61646cb92 100644
--- a/lib/portage/tests/util/futures/asyncio/test_subprocess_exec.py
+++ b/lib/portage/tests/util/futures/asyncio/test_subprocess_exec.py
@@ -3,61 +3,16 @@
 
 import os
 import subprocess
-
-try:
-       from asyncio import create_subprocess_exec
-except ImportError:
-       create_subprocess_exec = None
+import sys
 
 from portage.process import find_binary
 from portage.tests import TestCase
 from portage.util._eventloop.global_event_loop import global_event_loop
 from portage.util.futures import asyncio
-from portage.util.futures.executor.fork import ForkExecutor
+from portage.util.futures._asyncio import create_subprocess_exec
+from portage.util.futures._asyncio.streams import _reader as reader
+from portage.util.futures.compat_coroutine import coroutine, coroutine_return
 from portage.util.futures.unix_events import DefaultEventLoopPolicy
-from _emerge.PipeReader import PipeReader
-
-
-def reader(input_file, loop=None):
-       """
-       Asynchronously read a binary input file.
-
-       @param input_file: binary input file
-       @type input_file: file
-       @param loop: event loop
-       @type loop: EventLoop
-       @return: bytes
-       @rtype: asyncio.Future (or compatible)
-       """
-       loop = asyncio._wrap_loop(loop)
-       future = loop.create_future()
-       _Reader(future, input_file, loop)
-       return future
-
-
-class _Reader(object):
-       def __init__(self, future, input_file, loop):
-               self._future = future
-               self._pipe_reader = PipeReader(
-                       input_files={'input_file':input_file}, scheduler=loop)
-
-               self._future.add_done_callback(self._cancel_callback)
-               self._pipe_reader.addExitListener(self._eof)
-               self._pipe_reader.start()
-
-       def _cancel_callback(self, future):
-               if future.cancelled():
-                       self._cancel()
-
-       def _eof(self, pipe_reader):
-               self._pipe_reader = None
-               self._future.set_result(pipe_reader.getvalue())
-
-       def _cancel(self):
-               if self._pipe_reader is not None and self._pipe_reader.poll() 
is None:
-                       self._pipe_reader.removeExitListener(self._eof)
-                       self._pipe_reader.cancel()
-                       self._pipe_reader = None
 
 
 class SubprocessExecTestCase(TestCase):
@@ -76,99 +31,66 @@ class SubprocessExecTestCase(TestCase):
                                
self.assertFalse(global_event_loop().is_closed())
 
        def testEcho(self):
-               if create_subprocess_exec is None:
-                       self.skipTest('create_subprocess_exec not implemented 
for python2')
-
                args_tuple = (b'hello', b'world')
                echo_binary = find_binary("echo")
                self.assertNotEqual(echo_binary, None)
                echo_binary = echo_binary.encode()
 
-               # Use os.pipe(), since this loop does not implement the
-               # ReadTransport necessary for subprocess.PIPE support.
-               stdout_pr, stdout_pw = os.pipe()
-               stdout_pr = os.fdopen(stdout_pr, 'rb', 0)
-               stdout_pw = os.fdopen(stdout_pw, 'wb', 0)
-               files = [stdout_pr, stdout_pw]
-
                def test(loop):
-                       output = None
-                       try:
-                               with open(os.devnull, 'rb', 0) as devnull:
-                                       proc = loop.run_until_complete(
-                                               create_subprocess_exec(
-                                               echo_binary, *args_tuple,
-                                               stdin=devnull, 
stdout=stdout_pw, stderr=stdout_pw))
-
-                               # This belongs exclusively to the subprocess 
now.
-                               stdout_pw.close()
-
-                               output = asyncio.ensure_future(
-                                       reader(stdout_pr, loop=loop), loop=loop)
-
-                               self.assertEqual(
-                                       loop.run_until_complete(proc.wait()), 
os.EX_OK)
-                               self.assertEqual(
-                                       
tuple(loop.run_until_complete(output).split()), args_tuple)
-                       finally:
-                               if output is not None and not output.done():
-                                       output.cancel()
-                               for f in files:
-                                       f.close()
+                       @coroutine
+                       def test_coroutine(loop=None):
 
-               self._run_test(test)
+                               proc = (yield 
create_subprocess_exec(echo_binary, *args_tuple,
+                                               stdout=subprocess.PIPE, 
stderr=subprocess.STDOUT,
+                                               loop=loop))
 
-       def testCat(self):
-               if create_subprocess_exec is None:
-                       self.skipTest('create_subprocess_exec not implemented 
for python2')
+                               out, err = (yield proc.communicate())
+                               self.assertEqual(tuple(out.split()), args_tuple)
+                               self.assertEqual(proc.returncode, os.EX_OK)
 
-               stdin_data = b'hello world'
-               cat_binary = find_binary("cat")
-               self.assertNotEqual(cat_binary, None)
-               cat_binary = cat_binary.encode()
+                               proc = (yield create_subprocess_exec(
+                                               'bash', '-c', 'echo foo; echo 
bar 1>&2;',
+                                               stdout=subprocess.PIPE, 
stderr=subprocess.PIPE,
+                                               loop=loop))
 
-               # Use os.pipe(), since this loop does not implement the
-               # ReadTransport necessary for subprocess.PIPE support.
-               stdout_pr, stdout_pw = os.pipe()
-               stdout_pr = os.fdopen(stdout_pr, 'rb', 0)
-               stdout_pw = os.fdopen(stdout_pw, 'wb', 0)
+                               out, err = (yield proc.communicate())
+                               self.assertEqual(out, b'foo\n')
+                               self.assertEqual(err, b'bar\n')
+                               self.assertEqual(proc.returncode, os.EX_OK)
 
-               stdin_pr, stdin_pw = os.pipe()
-               stdin_pr = os.fdopen(stdin_pr, 'rb', 0)
-               stdin_pw = os.fdopen(stdin_pw, 'wb', 0)
+                               proc = (yield create_subprocess_exec(
+                                               'bash', '-c', 'echo foo; echo 
bar 1>&2;',
+                                               stdout=subprocess.PIPE, 
stderr=subprocess.STDOUT,
+                                               loop=loop))
 
-               files = [stdout_pr, stdout_pw, stdin_pr, stdin_pw]
+                               out, err = (yield proc.communicate())
+                               self.assertEqual(out, b'foo\nbar\n')
+                               self.assertEqual(err, None)
+                               self.assertEqual(proc.returncode, os.EX_OK)
 
-               def test(loop):
-                       output = None
-                       try:
-                               proc = loop.run_until_complete(
-                                       create_subprocess_exec(
-                                       cat_binary,
-                                       stdin=stdin_pr, stdout=stdout_pw, 
stderr=stdout_pw))
+                               coroutine_return('success')
 
-                               # These belong exclusively to the subprocess 
now.
-                               stdout_pw.close()
-                               stdin_pr.close()
+                       self.assertEqual('success',
+                               
loop.run_until_complete(test_coroutine(loop=loop)))
 
-                               output = asyncio.ensure_future(
-                                       reader(stdout_pr, loop=loop), loop=loop)
+               self._run_test(test)
 
-                               with ForkExecutor(loop=loop) as executor:
-                                       writer = 
asyncio.ensure_future(loop.run_in_executor(
-                                               executor, stdin_pw.write, 
stdin_data), loop=loop)
+       def testCat(self):
+               stdin_data = b'hello world'
+               cat_binary = find_binary("cat")
+               self.assertNotEqual(cat_binary, None)
+               cat_binary = cat_binary.encode()
 
-                                       # This belongs exclusively to the 
writer now.
-                                       stdin_pw.close()
-                                       loop.run_until_complete(writer)
+               def test(loop):
+                       proc = loop.run_until_complete(
+                               create_subprocess_exec(cat_binary,
+                               stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+                               loop=loop))
+
+                       out, err = 
loop.run_until_complete(proc.communicate(input=stdin_data))
 
-                               
self.assertEqual(loop.run_until_complete(proc.wait()), os.EX_OK)
-                               
self.assertEqual(loop.run_until_complete(output), stdin_data)
-                       finally:
-                               if output is not None and not output.done():
-                                       output.cancel()
-                               for f in files:
-                                       f.close()
+                       self.assertEqual(loop.run_until_complete(proc.wait()), 
os.EX_OK)
+                       self.assertEqual(out, stdin_data)
 
                self._run_test(test)
 
@@ -178,8 +100,8 @@ class SubprocessExecTestCase(TestCase):
                requires an AbstractEventLoop.connect_read_pipe implementation
                (and a ReadTransport implementation for it to return).
                """
-               if create_subprocess_exec is None:
-                       self.skipTest('create_subprocess_exec not implemented 
for python2')
+               if sys.version_info.major < 3:
+                       self.skipTest('ReadTransport not implemented for 
python2')
 
                args_tuple = (b'hello', b'world')
                echo_binary = find_binary("echo")
@@ -192,7 +114,8 @@ class SubprocessExecTestCase(TestCase):
                                        create_subprocess_exec(
                                        echo_binary, *args_tuple,
                                        stdin=devnull,
-                                       stdout=subprocess.PIPE, 
stderr=subprocess.STDOUT))
+                                       stdout=subprocess.PIPE, 
stderr=subprocess.STDOUT,
+                                       loop=loop))
 
                        self.assertEqual(
                                
tuple(loop.run_until_complete(proc.stdout.read()).split()),
@@ -207,8 +130,8 @@ class SubprocessExecTestCase(TestCase):
                requires an AbstractEventLoop.connect_write_pipe implementation
                (and a WriteTransport implementation for it to return).
                """
-               if create_subprocess_exec is None:
-                       self.skipTest('create_subprocess_exec not implemented 
for python2')
+               if sys.version_info.major < 3:
+                       self.skipTest('WriteTransport not implemented for 
python2')
 
                stdin_data = b'hello world'
                cat_binary = find_binary("cat")
@@ -220,7 +143,8 @@ class SubprocessExecTestCase(TestCase):
                                create_subprocess_exec(
                                cat_binary,
                                stdin=subprocess.PIPE,
-                               stdout=subprocess.PIPE, 
stderr=subprocess.STDOUT))
+                               stdout=subprocess.PIPE, 
stderr=subprocess.STDOUT,
+                               loop=loop))
 
                        # This buffers data when necessary to avoid blocking.
                        proc.stdin.write(stdin_data)

diff --git a/lib/portage/util/compression_probe.py 
b/lib/portage/util/compression_probe.py
index 29d0eedff..90880b1cd 100644
--- a/lib/portage/util/compression_probe.py
+++ b/lib/portage/util/compression_probe.py
@@ -45,7 +45,7 @@ _compressors = {
        },
        "zstd": {
                "compress": "zstd ${BINPKG_COMPRESS_FLAGS}",
-               "decompress": "zstd -d",
+               "decompress": "zstd -d --long=31",
                "package": "app-arch/zstd",
        },
 }

diff --git a/lib/portage/util/futures/_asyncio/__init__.py 
b/lib/portage/util/futures/_asyncio/__init__.py
index acfd59396..faab98e47 100644
--- a/lib/portage/util/futures/_asyncio/__init__.py
+++ b/lib/portage/util/futures/_asyncio/__init__.py
@@ -20,6 +20,9 @@ __all__ = (
        'wait',
 )
 
+import subprocess
+import sys
+
 try:
        import asyncio as _real_asyncio
 except ImportError:
@@ -45,6 +48,7 @@ from portage.util.futures.futures import (
        InvalidStateError,
        TimeoutError,
 )
+from portage.util.futures._asyncio.process import _Process
 from portage.util.futures._asyncio.tasks import (
        ALL_COMPLETED,
        FIRST_COMPLETED,
@@ -105,6 +109,49 @@ def set_child_watcher(watcher):
     return get_event_loop_policy().set_child_watcher(watcher)
 
 
+# Python 3.4 and later implement PEP 446, which makes newly
+# created file descriptors non-inheritable by default.
+_close_fds_default = sys.version_info < (3, 4)
+
+
+def create_subprocess_exec(*args, **kwargs):
+       """
+       Create a subprocess.
+
+       @param args: program and arguments
+       @type args: str
+       @param stdin: stdin file descriptor
+       @type stdin: file or int
+       @param stdout: stdout file descriptor
+       @type stdout: file or int
+       @param stderr: stderr file descriptor
+       @type stderr: file or int
+       @param close_fds: close file descriptors
+       @type close_fds: bool
+       @param loop: asyncio.AbstractEventLoop (or compatible)
+       @type loop: event loop
+       @type kwargs: varies
+       @param kwargs: subprocess.Popen parameters
+       @rtype: asyncio.Future (or compatible)
+       @return: subset of asyncio.subprocess.Process interface
+       """
+       loop = _wrap_loop(kwargs.pop('loop', None))
+       kwargs.setdefault('close_fds', _close_fds_default)
+       if _asyncio_enabled and isinstance(loop, _AsyncioEventLoop):
+               # Use the real asyncio loop and create_subprocess_exec.
+               return _real_asyncio.create_subprocess_exec(*args, 
loop=loop._loop, **kwargs)
+
+       result = loop.create_future()
+
+       result.set_result(_Process(subprocess.Popen(
+               args,
+               stdin=kwargs.pop('stdin', None),
+               stdout=kwargs.pop('stdout', None),
+               stderr=kwargs.pop('stderr', None), **kwargs), loop))
+
+       return result
+
+
 class Task(Future):
        """
        Schedule the execution of a coroutine: wrap it in a future. A task
@@ -127,6 +174,12 @@ def ensure_future(coro_or_future, loop=None):
        @rtype: asyncio.Future (or compatible)
        @return: an instance of Future
        """
+       loop = _wrap_loop(loop)
+       if _asyncio_enabled and isinstance(loop, _AsyncioEventLoop):
+               # Use the real asyncio loop and ensure_future.
+               return _real_asyncio.ensure_future(
+                       coro_or_future, loop=loop._loop)
+
        if isinstance(coro_or_future, Future):
                return coro_or_future
        raise NotImplementedError

diff --git a/lib/portage/util/futures/_asyncio/process.py 
b/lib/portage/util/futures/_asyncio/process.py
new file mode 100644
index 000000000..020164c9b
--- /dev/null
+++ b/lib/portage/util/futures/_asyncio/process.py
@@ -0,0 +1,107 @@
+# Copyright 2018 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+import portage
+portage.proxy.lazyimport.lazyimport(globals(),
+       'portage.util.futures:asyncio',
+)
+from portage.util.futures._asyncio.streams import _reader, _writer
+from portage.util.futures.compat_coroutine import coroutine, coroutine_return
+
+
+class _Process(object):
+       """
+       Emulate a subset of the asyncio.subprocess.Process interface,
+       for python2.
+       """
+       def __init__(self, proc, loop):
+               """
+               @param proc: process instance
+               @type proc: subprocess.Popen
+               @param loop: asyncio.AbstractEventLoop (or compatible)
+               @type loop: event loop
+               """
+               self._proc = proc
+               self._loop = loop
+               self.terminate = proc.terminate
+               self.kill = proc.kill
+               self.send_signal = proc.send_signal
+               self.pid = proc.pid
+               self._waiters = []
+               loop._asyncio_child_watcher.\
+                       add_child_handler(self.pid, self._proc_exit)
+
+       @property
+       def returncode(self):
+               return self._proc.returncode
+
+       @coroutine
+       def communicate(self, input=None):
+               """
+               Read data from stdout and stderr, until end-of-file is reached.
+               Wait for process to terminate.
+
+               @param input: stdin content to write
+               @type input: bytes
+               @return: tuple (stdout_data, stderr_data)
+               @rtype: asyncio.Future (or compatible)
+               """
+               futures = []
+               for input_file in (self._proc.stdout, self._proc.stderr):
+                       if input_file is None:
+                               future = self._loop.create_future()
+                               future.set_result(None)
+                       else:
+                               future = _reader(input_file, loop=self._loop)
+                       futures.append(future)
+
+               writer = None
+               if input is not None:
+                       if self._proc.stdin is None:
+                               raise TypeError('communicate: expected file or 
int, got {}'.format(type(self._proc.stdin)))
+                       writer = 
asyncio.ensure_future(_writer(self._proc.stdin, input), loop=self._loop)
+
+               try:
+                       yield asyncio.wait(futures + [self.wait()], 
loop=self._loop)
+               finally:
+                       if writer is not None:
+                               if writer.done():
+                                       # Consume expected exceptions.
+                                       try:
+                                               writer.result()
+                                       except EnvironmentError:
+                                               # This is normal if the other 
end of the pipe was closed.
+                                               pass
+                               else:
+                                       writer.cancel()
+
+               coroutine_return(tuple(future.result() for future in futures))
+
+       def wait(self):
+               """
+               Wait for child process to terminate. Set and return returncode 
attribute.
+
+               @return: returncode
+               @rtype: asyncio.Future (or compatible)
+               """
+               waiter = self._loop.create_future()
+               if self.returncode is None:
+                       self._waiters.append(waiter)
+                       waiter.add_done_callback(self._waiter_cancel)
+               else:
+                       waiter.set_result(self.returncode)
+               return waiter
+
+       def _waiter_cancel(self, waiter):
+               if waiter.cancelled():
+                       try:
+                               self._waiters.remove(waiter)
+                       except ValueError:
+                               pass
+
+       def _proc_exit(self, pid, returncode):
+               self._proc.returncode = returncode
+               waiters = self._waiters
+               self._waiters = []
+               for waiter in waiters:
+                       waiter.set_result(returncode)

diff --git a/lib/portage/util/futures/_asyncio/streams.py 
b/lib/portage/util/futures/_asyncio/streams.py
new file mode 100644
index 000000000..650a16491
--- /dev/null
+++ b/lib/portage/util/futures/_asyncio/streams.py
@@ -0,0 +1,96 @@
+# Copyright 2018 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+import errno
+import os
+
+import portage
+portage.proxy.lazyimport.lazyimport(globals(),
+       '_emerge.PipeReader:PipeReader',
+       'portage.util.futures:asyncio',
+       'portage.util.futures.unix_events:_set_nonblocking',
+)
+from portage.util.futures.compat_coroutine import coroutine
+
+
+def _reader(input_file, loop=None):
+       """
+       Asynchronously read a binary input file, and close it when
+       it reaches EOF.
+
+       @param input_file: binary input file descriptor
+       @type input_file: file or int
+       @param loop: asyncio.AbstractEventLoop (or compatible)
+       @type loop: event loop
+       @return: bytes
+       @rtype: asyncio.Future (or compatible)
+       """
+       loop = asyncio._wrap_loop(loop)
+       future = loop.create_future()
+       _Reader(future, input_file, loop)
+       return future
+
+
+class _Reader(object):
+       def __init__(self, future, input_file, loop):
+               self._future = future
+               self._pipe_reader = PipeReader(
+                       input_files={'input_file':input_file}, scheduler=loop)
+
+               self._future.add_done_callback(self._cancel_callback)
+               self._pipe_reader.addExitListener(self._eof)
+               self._pipe_reader.start()
+
+       def _cancel_callback(self, future):
+               if future.cancelled():
+                       self._cancel()
+
+       def _eof(self, pipe_reader):
+               self._pipe_reader = None
+               self._future.set_result(pipe_reader.getvalue())
+
+       def _cancel(self):
+               if self._pipe_reader is not None and self._pipe_reader.poll() 
is None:
+                       self._pipe_reader.removeExitListener(self._eof)
+                       self._pipe_reader.cancel()
+                       self._pipe_reader = None
+
+
+@coroutine
+def _writer(output_file, content, loop=None):
+       """
+       Asynchronously write bytes to output file, and close it when
+       done. If an EnvironmentError other than EAGAIN is encountered,
+       which typically indicates that the other end of the pipe has
+       close, the error is raised. This function is a coroutine.
+
+       @param output_file: output file descriptor
+       @type output_file: file or int
+       @param content: content to write
+       @type content: bytes
+       @param loop: asyncio.AbstractEventLoop (or compatible)
+       @type loop: event loop
+       """
+       fd = output_file if isinstance(output_file, int) else 
output_file.fileno()
+       _set_nonblocking(fd)
+       loop = asyncio._wrap_loop(loop)
+       try:
+               while content:
+                       waiter = loop.create_future()
+                       loop.add_writer(fd, lambda: waiter.set_result(None))
+                       try:
+                               yield waiter
+                               while content:
+                                       try:
+                                               content = content[os.write(fd, 
content):]
+                                       except EnvironmentError as e:
+                                               if e.errno == errno.EAGAIN:
+                                                       break
+                                               else:
+                                                       raise
+                       finally:
+                               loop.remove_writer(fd)
+       except GeneratorExit:
+               raise
+       finally:
+               os.close(output_file) if isinstance(output_file, int) else 
output_file.close()

diff --git a/lib/portage/util/futures/compat_coroutine.py 
b/lib/portage/util/futures/compat_coroutine.py
index 17400b74d..59fdc31b6 100644
--- a/lib/portage/util/futures/compat_coroutine.py
+++ b/lib/portage/util/futures/compat_coroutine.py
@@ -1,9 +1,13 @@
 # Copyright 2018 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 
-from portage.util.futures import asyncio
 import functools
 
+import portage
+portage.proxy.lazyimport.lazyimport(globals(),
+       'portage.util.futures:asyncio',
+)
+
 
 def coroutine(generator_func):
        """

diff --git a/man/emerge.1 b/man/emerge.1
index 7003cf29e..af553fcb5 100644
--- a/man/emerge.1
+++ b/man/emerge.1
@@ -22,7 +22,7 @@ emerge \- Command\-line interface to the Portage system
 \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
+\fBemerge\fR can also update the \fBebuild repository\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
@@ -198,7 +198,7 @@ the emerge output of the next \-\-depclean run carefully! 
Use
 .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
+repository.  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
@@ -227,7 +227,7 @@ explicitly discarded by running `emaint \-\-fix 
cleanresume` (see
 \fBemaint\fR(1)).
 .TP
 .BR \-\-search ", " \-s
-Searches for matches of the supplied string in the portage tree.
+Searches for matches of the supplied string in the ebuild repository.
 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
@@ -264,7 +264,7 @@ more information about sync operations.
 
 \fBNOTE:\fR
 The \fBemerge\-webrsync\fR program will download the entire
-portage tree as a tarball, which is much faster than emerge
+ebuild repository as a tarball, which is much faster than emerge
 \-\-sync for first time syncs.
 
 .TP
@@ -1230,7 +1230,7 @@ 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
+update a large number of packages if the ebuild repository has been 
particularly
 active.
 .LP
 You also want to typically use \fB\-\-update\fR, which ignores packages that

diff --git a/man/make.conf.5 b/man/make.conf.5
index 2c7b0fc17..127a62e44 100644
--- a/man/make.conf.5
+++ b/man/make.conf.5
@@ -1107,7 +1107,7 @@ Defaults to /usr/portage/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.
+is used to sync the local ebuild repository when `emerge \-\-sync` is run.
 
 Note that the \fBSYNC\fR variable is now deprecated, and instead the
 sync\-type and sync\-uri attributes in repos.conf should be used. See

diff --git a/man/portage.5 b/man/portage.5
index cd9d5036d..c3c610a6c 100644
--- a/man/portage.5
+++ b/man/portage.5
@@ -214,7 +214,7 @@ More reading:
 .TP
 \fB/etc/portage/make.profile/\fR or \fB/etc/make.profile/\fR
 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
+\fB/usr/portage/profiles/\fR.  Since it is part of the ebuild repository, 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 \fBmake.profile\fR
@@ -1666,13 +1666,13 @@ again.
 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
+The format follows somewhat closely that of the ebuild repository. 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).
+can be unmerged without needing the ebuild repository).
 
 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

diff --git a/repoman/README b/repoman/README
index 5e78842c9..f0976e841 100644
--- a/repoman/README
+++ b/repoman/README
@@ -3,7 +3,7 @@ About Portage
 
 Portage is a package management system based on ports collections. The
 Package Manager Specification Project (PMS) standardises and documents
-the behaviour of Portage so that the Portage tree can be used by other
+the behaviour of Portage so that ebuild repositories can be used by other
 package managers.
 
 

diff --git a/repoman/lib/repoman/__init__.py b/repoman/lib/repoman/__init__.py
index 89779b95c..301b34309 100644
--- a/repoman/lib/repoman/__init__.py
+++ b/repoman/lib/repoman/__init__.py
@@ -14,7 +14,7 @@ except ImportError as e:
        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("!!! ebuild repository 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")

diff --git a/repoman/lib/repoman/checks/herds/__init__.py 
b/repoman/lib/repoman/checks/herds/__init__.py
deleted file mode 100644
index e69de29bb..000000000

diff --git a/repoman/lib/repoman/checks/herds/herdbase.py 
b/repoman/lib/repoman/checks/herds/herdbase.py
deleted file mode 100644
index ebe6a19b4..000000000
--- a/repoman/lib/repoman/checks/herds/herdbase.py
+++ /dev/null
@@ -1,135 +0,0 @@
-# -*- coding: utf-8 -*-
-# repoman: Herd database analysis
-# Copyright 2010-2013 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2 or later
-
-from __future__ import print_function, unicode_literals
-
-import errno
-import xml.etree.ElementTree
-try:
-       from xml.parsers.expat import ExpatError
-except (SystemExit, KeyboardInterrupt):
-       raise
-except (ImportError, SystemError, RuntimeError, Exception):
-       # broken or missing xml support
-       # https://bugs.python.org/issue14988
-       # This means that python is built without xml support.
-       # We tolerate global scope import failures for optional
-       # modules, so that ImportModulesTestCase can succeed (or
-       # possibly alert us about unexpected import failures).
-       pass
-
-from portage import _encodings, _unicode_encode
-from portage.exception import FileNotFound, ParseError, PermissionDenied
-from portage import os
-
-from repoman.errors import err
-
-__all__ = [
-       "make_herd_base", "get_herd_base"
-]
-
-
-def _make_email(nick_name):
-       if not nick_name.endswith('@gentoo.org'):
-               nick_name = nick_name + '@gentoo.org'
-       return nick_name
-
-
-class HerdBase(object):
-       def __init__(self, herd_to_emails, all_emails):
-               self.herd_to_emails = herd_to_emails
-               self.all_emails = all_emails
-
-       def known_herd(self, herd_name):
-               return herd_name in self.herd_to_emails
-
-       def known_maintainer(self, nick_name):
-               return _make_email(nick_name) in self.all_emails
-
-       def maintainer_in_herd(self, nick_name, herd_name):
-               return _make_email(nick_name) in self.herd_to_emails[herd_name]
-
-
-class _HerdsTreeBuilder(xml.etree.ElementTree.TreeBuilder):
-       """
-       Implements doctype() as required to avoid deprecation warnings with
-       >=python-2.7.
-       """
-       def doctype(self, name, pubid, system):
-               pass
-
-
-def make_herd_base(filename):
-       herd_to_emails = dict()
-       all_emails = set()
-
-       try:
-               xml_tree = xml.etree.ElementTree.parse(
-                       _unicode_encode(
-                               filename, encoding=_encodings['fs'], 
errors='strict'),
-                       parser=xml.etree.ElementTree.XMLParser(
-                               target=_HerdsTreeBuilder()))
-       except ExpatError as e:
-               raise ParseError("metadata.xml: %s" % (e,))
-       except EnvironmentError as e:
-               func_call = "open('%s')" % filename
-               if e.errno == errno.EACCES:
-                       raise PermissionDenied(func_call)
-               elif e.errno == errno.ENOENT:
-                       raise FileNotFound(filename)
-               raise
-
-       herds = xml_tree.findall('herd')
-       for h in herds:
-               _herd_name = h.find('name')
-               if _herd_name is None:
-                       continue
-               herd_name = _herd_name.text.strip()
-               del _herd_name
-
-               maintainers = h.findall('maintainer')
-               herd_emails = set()
-               for m in maintainers:
-                       _m_email = m.find('email')
-                       if _m_email is None:
-                               continue
-                       m_email = _m_email.text.strip()
-
-                       herd_emails.add(m_email)
-                       all_emails.add(m_email)
-
-               herd_to_emails[herd_name] = herd_emails
-
-       return HerdBase(herd_to_emails, all_emails)
-
-
-def get_herd_base(repoman_settings):
-       try:
-               herd_base = make_herd_base(
-                       os.path.join(repoman_settings["PORTDIR"], 
"metadata/herds.xml"))
-       except (EnvironmentError, ParseError, PermissionDenied) as e:
-               err(str(e))
-       except FileNotFound:
-               # TODO: Download as we do for metadata.dtd, but add a way to
-               # disable for non-gentoo repoman users who may not have herds.
-               herd_base = None
-       return herd_base
-
-
-if __name__ == '__main__':
-       h = make_herd_base('/usr/portage/metadata/herds.xml')
-
-       assert(h.known_herd('sound'))
-       assert(not h.known_herd('media-sound'))
-
-       assert(h.known_maintainer('sping'))
-       assert(h.known_maintainer('[email protected]'))
-       assert(not h.known_maintainer('portage'))
-
-       assert(h.maintainer_in_herd('[email protected]', 'tools-portage'))
-       assert(not h.maintainer_in_herd('[email protected]', 'tools-portage'))
-
-       import pprint
-       pprint.pprint(h.herd_to_emails)

diff --git a/repoman/lib/repoman/checks/herds/metadata.py 
b/repoman/lib/repoman/checks/herds/metadata.py
deleted file mode 100644
index b4a433ed7..000000000
--- a/repoman/lib/repoman/checks/herds/metadata.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding:utf-8 -*-
-
-
-class UnknownHerdsError(ValueError):
-       def __init__(self, herd_names):
-               _plural = len(herd_names) != 1
-               super(UnknownHerdsError, self).__init__(
-                       'Unknown %s %s' % (
-                               _plural and 'herds' or 'herd',
-                               ','.join('"%s"' % e for e in herd_names)))
-
-
-def check_metadata_herds(xml_tree, herd_base):
-       herd_nodes = xml_tree.findall('herd')
-       unknown_herds = [
-               name for name in (
-                       e.text.strip() for e in herd_nodes if e.text is not 
None)
-               if not herd_base.known_herd(name)]
-
-       if unknown_herds:
-               raise UnknownHerdsError(unknown_herds)
-
-
-def check_metadata(xml_tree, herd_base):
-       if herd_base is not None:
-               check_metadata_herds(xml_tree, herd_base)

diff --git a/repoman/lib/repoman/utilities.py b/repoman/lib/repoman/utilities.py
index 1272f3fb6..790d5e516 100644
--- a/repoman/lib/repoman/utilities.py
+++ b/repoman/lib/repoman/utilities.py
@@ -256,7 +256,7 @@ def FindPortdir(settings):
        pwd = _unicode_decode(os.environ.get('PWD', ''), 
encoding=_encodings['fs'])
        if pwd and pwd != location and os.path.realpath(pwd) == location:
                # 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.
+               # orient itself if the user has symlinks in their repository 
structure.
                # We use os.environ["PWD"], if available, to get the 
non-canonical path of
                # the current working directory (from the shell).
                location = pwd

diff --git a/repoman/man/repoman.1 b/repoman/man/repoman.1
index dea17c3b4..766146f57 100644
--- a/repoman/man/repoman.1
+++ b/repoman/man/repoman.1
@@ -1,7 +1,7 @@
 .TH "REPOMAN" "1" "Mar 2018" "Repoman VERSION" "Repoman"
 .SH NAME
 repoman \- Gentoo's program to enforce a minimal level of quality assurance in
-packages added to the portage tree
+packages added to the ebuild repository
 .SH SYNOPSIS
 \fBrepoman\fR [\fIoption\fR] [\fImode\fR]
 .SH DESCRIPTION

diff --git a/setup.py b/setup.py
index 52cda62d0..7cb4e2eb7 100755
--- a/setup.py
+++ b/setup.py
@@ -662,7 +662,7 @@ class build_ext(_build_ext):
 
 setup(
        name = 'portage',
-       version = '2.3.44',
+       version = '2.3.45',
        url = 'https://wiki.gentoo.org/wiki/Project:Portage',
        author = 'Gentoo Portage Development Team',
        author_email = '[email protected]',

Reply via email to