If there are packages to be merged and "buildpkg" or "buildsyspkg" is
enabled, then bail out early if PKGDIR is not writable (in order to
avoid a fatal EROFS error which would otherwise occur later on).
Behavior remains unchanged for --pretend, --fetchonly and
--fetch-all-uri. For --ask, it will bail out just after the last
relevant --ask prompt.

X-Gentoo-Bug: 490732
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=490732
---
 pym/_emerge/actions.py       | 28 ++++++++++++++++++++++++++--
 pym/portage/dbapi/bintree.py | 12 ++++++++++++
 2 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/pym/_emerge/actions.py b/pym/_emerge/actions.py
index 6f7dfe0..dec5b04 100644
--- a/pym/_emerge/actions.py
+++ b/pym/_emerge/actions.py
@@ -428,7 +428,18 @@ def action_build(settings, trees, mtimedb,
                        # least show warnings about missed updates and such.
                        mydepgraph.display_problems()
 
-               if not Scheduler._opts_no_self_update.intersection(myopts):
+
+               need_write_vardb = not Scheduler. \
+                       _opts_no_self_update.intersection(myopts)
+
+               need_write_bindb = not any(x in myopts for x in
+                       ("--fetchonly", "--fetch-all-uri", "--pretend")) and \
+                       (any("buildpkg" in trees[eroot]["root_config"].
+                               settings.features for eroot in trees) or
+                       any("buildsyspkg" in trees[eroot]["root_config"].
+                               settings.features for eroot in trees))
+
+               if need_write_bindb or need_write_vardb:
 
                        eroots = set()
                        for x in mydepgraph.altlist():
@@ -436,13 +447,26 @@ def action_build(settings, trees, mtimedb,
                                        eroots.add(x.root)
 
                        for eroot in eroots:
-                               if not trees[eroot]["vartree"].dbapi.writable:
+                               if need_write_vardb and \
+                                       not 
trees[eroot]["vartree"].dbapi.writable:
                                        writemsg_level("!!! %s\n" %
                                                _("Read-only file system: %s") %
                                                
trees[eroot]["vartree"].dbapi._dbroot,
                                                level=logging.ERROR, 
noiselevel=-1)
                                        return 1
 
+                               if need_write_bindb and \
+                                       ("buildpkg" in 
trees[eroot]["root_config"].
+                                       settings.features or
+                                       "buildsyspkg" in 
trees[eroot]["root_config"].
+                                       settings.features) and \
+                                       not 
trees[eroot]["bintree"].dbapi.writable:
+                                       writemsg_level("!!! %s\n" %
+                                               _("Read-only file system: %s") %
+                                               trees[eroot]["bintree"].pkgdir,
+                                               level=logging.ERROR, 
noiselevel=-1)
+                                       return 1
+
                if ("--resume" in myopts):
                        favorites=mtimedb["resume"]["favorites"]
 
diff --git a/pym/portage/dbapi/bintree.py b/pym/portage/dbapi/bintree.py
index a5d7ac9..b56c8c1 100644
--- a/pym/portage/dbapi/bintree.py
+++ b/pym/portage/dbapi/bintree.py
@@ -18,6 +18,7 @@ portage.proxy.lazyimport.lazyimport(globals(),
        'portage.util:atomic_ofstream,ensure_dirs,normalize_path,' + \
                'writemsg,writemsg_stdout',
        'portage.util.listdir:listdir',
+       'portage.util.path:first_existing',
        'portage.util._urlopen:urlopen@_urlopen',
        'portage.versions:best,catpkgsplit,catsplit,_pkg_str',
 )
@@ -85,6 +86,17 @@ class bindbapi(fakedbapi):
                self._aux_cache_slot_dict = 
slot_dict_class(self._aux_cache_keys)
                self._aux_cache = {}
 
+       @property
+       def writable(self):
+               """
+               Check if PKGDIR is writable, or permissions are sufficient
+               to create it if it does not exist yet.
+               @rtype: bool
+               @return: True if PKGDIR is writable or can be created,
+                       False otherwise
+               """
+               return os.access(first_existing(self.bintree.pkgdir), os.W_OK)
+
        def match(self, *pargs, **kwargs):
                if self.bintree and not self.bintree.populated:
                        self.bintree.populate()
-- 
2.0.4


Reply via email to