Specify the root to use as the --quickpkg-direct package source. This
root is assumed to be immutable during the entire emerge operation.
The default is set to "/".

Bug: https://bugs.gentoo.org/752066
Signed-off-by: Zac Medico <zmed...@gentoo.org>
---
 lib/_emerge/actions.py                  | 19 ++++++++++++++++---
 lib/_emerge/depgraph.py                 | 11 +++++++++--
 lib/_emerge/main.py                     |  5 +++++
 lib/portage/tests/emerge/test_simple.py |  3 ++-
 man/emerge.1                            | 10 ++++++++--
 5 files changed, 40 insertions(+), 8 deletions(-)

diff --git a/lib/_emerge/actions.py b/lib/_emerge/actions.py
index 5e8a46957..2e155899c 100644
--- a/lib/_emerge/actions.py
+++ b/lib/_emerge/actions.py
@@ -49,7 +49,7 @@ from portage.package.ebuild._ipc.QueryCommand import 
QueryCommand
 from portage.package.ebuild.fetch import _hide_url_passwd
 from portage._sets import load_default_config, SETPREFIX
 from portage._sets.base import InternalPackageSet
-from portage.util import cmp_sort_key, writemsg, varexpand, \
+from portage.util import cmp_sort_key, normalize_path, writemsg, varexpand, \
        writemsg_level, writemsg_stdout
 from portage.util.digraph import digraph
 from portage.util.SlotObject import SlotObject
@@ -106,13 +106,26 @@ def action_build(emerge_config, trees=DeprecationWarning,
        # before we get here, so warn if they're not (bug #267103).
        chk_updated_cfg_files(settings['EROOT'], ['/etc/portage'])
 
+       quickpkg_root = normalize_path(os.path.abspath(
+               emerge_config.opts.get('--quickpkg-direct-root',
+               
emerge_config.running_config.settings['ROOT']))).rstrip(os.path.sep) + 
os.path.sep
        quickpkg_direct = ("--usepkg" in emerge_config.opts and
                emerge_config.opts.get('--quickpkg-direct', 'n') == 'y' and
-               emerge_config.target_config is not emerge_config.running_config)
+               emerge_config.target_config.settings['ROOT'] != quickpkg_root)
        if '--getbinpkg' in emerge_config.opts or quickpkg_direct:
                kwargs = {}
                if quickpkg_direct:
-                       kwargs['add_repos'] = 
(emerge_config.running_config.trees['vartree'].dbapi,)
+                       if quickpkg_root == emerge_config.running_config.root:
+                               quickpkg_vardb = 
emerge_config.running_config.trees['vartree'].dbapi
+                       else:
+                               quickpkg_settings = portage.config(
+                                       
config_root=emerge_config.target_config.settings['PORTAGE_CONFIGROOT'],
+                                       target_root=quickpkg_root,
+                                       
env=emerge_config.target_config.settings.backupenv,
+                                       
sysroot=emerge_config.target_config.settings['SYSROOT'],
+                                       
eprefix=emerge_config.target_config.settings['EPREFIX'])
+                               quickpkg_vardb = 
portage.vartree(settings=quickpkg_settings).dbapi
+                       kwargs['add_repos'] = (quickpkg_vardb,)
 
                try:
                        emerge_config.target_config.trees['bintree'].populate(
diff --git a/lib/_emerge/depgraph.py b/lib/_emerge/depgraph.py
index 0bb0352e7..898cf6c1a 100644
--- a/lib/_emerge/depgraph.py
+++ b/lib/_emerge/depgraph.py
@@ -41,7 +41,7 @@ from portage._sets import SETPREFIX
 from portage._sets.base import InternalPackageSet
 from portage.util import ConfigProtect, shlex_split, new_protect_filename
 from portage.util import cmp_sort_key, writemsg, writemsg_stdout
-from portage.util import ensure_dirs
+from portage.util import ensure_dirs, normalize_path
 from portage.util import writemsg_level, write_atomic
 from portage.util.digraph import digraph
 from portage.util.futures import asyncio
@@ -4567,8 +4567,15 @@ class depgraph:
                                self._dynamic_config._skip_restart = True
                                return False, myfavorites
 
+               # Since --quickpkg-direct assumes that --quickpkg-direct-root is
+               # immutable, assert that there are no merged or unmerge tasks
+               # for --quickpkg-direct-root.
+               quickpkg_root = normalize_path(os.path.abspath(
+                       self._frozen_config.myopts.get('--quickpkg-direct-root',
+                       
self._frozen_config._running_root.settings['ROOT']))).rstrip(os.path.sep) + 
os.path.sep
                if (self._frozen_config.myopts.get('--quickpkg-direct', 'n') == 
'y' and
-                       self._frozen_config.target_root is not 
self._frozen_config._running_root):
+                       self._frozen_config.settings['ROOT'] != quickpkg_root 
and
+                       self._frozen_config._running_root.settings['ROOT'] == 
quickpkg_root):
                        running_root = self._frozen_config._running_root.root
                        for node in self._dynamic_config.digraph:
                                if (isinstance(node, Package) and 
node.operation in ('merge', 'uninstall') and
diff --git a/lib/_emerge/main.py b/lib/_emerge/main.py
index 5075f7f57..0ac25ea36 100644
--- a/lib/_emerge/main.py
+++ b/lib/_emerge/main.py
@@ -645,6 +645,11 @@ def parse_opts(tmpcmdline, silent=False):
                        "choices": y_or_n
                },
 
+               "--quickpkg-direct-root": {
+                       "help": "Specify the root to use as the 
--quickpkg-direct package source",
+                       "action" : "store"
+               },
+
                "--quiet": {
                        "shortopt" : "-q",
                        "help"     : "reduced or condensed output",
diff --git a/lib/portage/tests/emerge/test_simple.py 
b/lib/portage/tests/emerge/test_simple.py
index 8ba74c609..1638fcb66 100644
--- a/lib/portage/tests/emerge/test_simple.py
+++ b/lib/portage/tests/emerge/test_simple.py
@@ -292,7 +292,8 @@ call_has_and_best_version() {
                        path=binhost_remote_path)
 
                test_commands = (
-                       emerge_cmd + ("--usepkgonly", "--root", cross_root, 
"--quickpkg-direct=y", "dev-libs/A"),
+                       emerge_cmd + ("--usepkgonly", "--root", cross_root, 
"--quickpkg-direct=y", "--quickpkg-direct-root", "/", "dev-libs/A"),
+                       emerge_cmd + ("--usepkgonly", "--quickpkg-direct=y", 
"--quickpkg-direct-root", cross_root, "dev-libs/A"),
                        env_update_cmd,
                        portageq_cmd + ("envvar", "-v", "CONFIG_PROTECT", 
"EROOT",
                                "PORTAGE_CONFIGROOT", "PORTAGE_TMPDIR", 
"USERLAND"),
diff --git a/man/emerge.1 b/man/emerge.1
index c1bcd0220..1a2a3fd3d 100644
--- a/man/emerge.1
+++ b/man/emerge.1
@@ -1,4 +1,4 @@
-.TH "EMERGE" "1" "Nov 2019" "Portage VERSION" "Portage"
+.TH "EMERGE" "1" "Nov 2020" "Portage VERSION" "Portage"
 .SH "NAME"
 emerge \- Command\-line interface to the Portage system
 .SH "SYNOPSIS"
@@ -844,7 +844,8 @@ b   blocked by another package (automatically resolved 
conflict)
 Enable use of installed packages directly as binary packages. This is
 similar to using binary packages produced by \fBquickpkg\fR(1), but
 installed packages are used directly as though they are binary packages.
-This option only works in combination with the \fB\-\-root=DIR\fR option,
+If \fB\-\-quickpkg\-direct\-root=DIR\fR is not also set to something
+other than "/", then \fB\-\-root=DIR\fR must be used,
 and it comes with the caveat that packages are only allowed to be
 installed into the root that is specified by the \fB\-\-root=DIR\fR
 option (the other root which serves as a source of packages is
@@ -857,6 +858,11 @@ quickpkg options are \fI\-\-include\-config\fR and
 man page). When a configuration file is not included because it is
 protected, an ewarn message is logged.
 .TP
+.BR \-\-quickpkg\-direct\-root=DIR
+Specify the root to use as the \fB\-\-quickpkg\-direct\fR package source.
+This root is assumed to be immutable during the entire emerge operation.
+The default is set to "/".
+.TP
 .BR "\-\-quiet [ y | n ]" ", " \-q
 Results may vary, but the general outcome is a reduced or condensed
 output from portage's displays.
-- 
2.26.2


Reply via email to