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]',