[gentoo-commits] proj/portage:master commit in: pym/_emerge/, pym/portage/dbapi/
commit: 27eeeb6e4fc8e68efa003b2db5bbd8cc4afe336a Author: Zac Medico gentoo org> AuthorDate: Fri Jul 13 22:19:29 2018 + Commit: Zac Medico gentoo org> CommitDate: Sun Jul 15 05:10:51 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=27eeeb6e portdbapi.cp_list: cache repo associations (bug 650814) Make portdbapi.cp_list return _pkg_str instances that have a 'repo' attribute (bindbapi.cp_list already does this), with results in ascending order by (pkg.version, repo.priority). Optimize portdbapi.findname2 to use the 'repo' attribute to enable cached results for files previously found by the portdbapi.cp_list method, avoiding filesystem access when possible. Optimize the depgraph._iter_match_pkgs_atom method by elimination of the repo loop, since portdbapi.cp_list now returns separate items when the same package version is found in multiple repos. Bug: https://bugs.gentoo.org/650814 Reviewed-by: Brian Dolbec gentoo.org> pym/_emerge/depgraph.py | 12 +++- pym/portage/dbapi/porttree.py | 41 + 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index 42857c1a5..b63d4f242 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -5613,10 +5613,6 @@ class depgraph(object): if cp_list: atom_set = InternalPackageSet(initial_atoms=(atom,), allow_repo=True) - if atom.repo is None and hasattr(db, "getRepositories"): - repo_list = db.getRepositories(catpkg=atom_exp.cp) - else: - repo_list = [atom.repo] # descending order cp_list.reverse() @@ -5624,13 +5620,11 @@ class depgraph(object): # Call match_from_list on one cpv at a time, in order # to avoid unnecessary match_from_list comparisons on # versions that are never yielded from this method. - if not match_from_list(atom_exp, [cpv]): - continue - for repo in repo_list: - + if match_from_list(atom_exp, [cpv]): try: pkg = self._pkg(cpv, pkg_type, root_config, - installed=installed, onlydeps=onlydeps, myrepo=repo) + installed=installed, onlydeps=onlydeps, + myrepo=getattr(cpv, 'repo', None)) except portage.exception.PackageNotFound: pass else: diff --git a/pym/portage/dbapi/porttree.py b/pym/portage/dbapi/porttree.py index 3e36024ff..f6076ee2b 100644 --- a/pym/portage/dbapi/porttree.py +++ b/pym/portage/dbapi/porttree.py @@ -459,6 +459,9 @@ class portdbapi(dbapi): mytree = self.treemap.get(myrepo) if mytree is None: return (None, 0) + elif mytree is not None: + # myrepo enables cached results when available + myrepo = self.repositories.location_map.get(mytree) mysplit = mycpv.split("/") psplit = pkgsplit(mysplit[1]) @@ -495,6 +498,14 @@ class portdbapi(dbapi): relative_path = mysplit[0] + _os.sep + psplit[0] + _os.sep + \ mysplit[1] + ".ebuild" + # There is no need to access the filesystem when the package + # comes from this db and the package repo attribute corresponds + # to the desired repo, since the file was previously found by + # the cp_list method. + if (myrepo is not None and myrepo == getattr(mycpv, 'repo', None) + and self is getattr(mycpv, '_db', None)): + return (mytree + _os.sep + relative_path, mytree) + for x in mytrees: filename = x + _os.sep + relative_path if _os.access(_unicode_encode(filename, @@ -950,18 +961,23 @@ class portdbapi(dbapi): return cachelist[:] mysplit = mycp.split("/") invalid_category = mysplit[0] not in self._categories - d={} + # Process repos in ascending order by repo.priority, so that + # stable sort by version produces results ordered by + # (pkg.version, repo.priority). if mytree is not None:
[gentoo-commits] proj/portage:master commit in: pym/_emerge/, pym/portage/dbapi/
commit: e691f07bf0572fad7686a54d628c1a29aec4ebe4 Author: Zac Medico gentoo org> AuthorDate: Thu Jul 12 09:48:32 2018 + Commit: Zac Medico gentoo org> CommitDate: Sat Jul 14 23:31:34 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=e691f07b dbapi: fix repoman implicit IUSE (bug 660982) Account for repoman modifications of the portdbapi self.settings reference, and treat all flags as valid for the empty profile because it does not have any implicit IUSE settings. Bug: https://bugs.gentoo.org/660982 Reviewed-by: Brian Dolbec gentoo.org> pym/_emerge/Package.py| 5 - pym/portage/dbapi/__init__.py | 16 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/pym/_emerge/Package.py b/pym/_emerge/Package.py index a7ce00bc9..5f34f3d27 100644 --- a/pym/_emerge/Package.py +++ b/pym/_emerge/Package.py @@ -93,7 +93,10 @@ class Package(Task): # sync metadata with validated repo (may be UNKNOWN_REPO) self._metadata['repository'] = self.cpv.repo - implicit_match = db._iuse_implicit_cnstr(self.cpv, self._metadata) + if self.root_config.settings.local_config: + implicit_match = db._iuse_implicit_cnstr(self.cpv, self._metadata) + else: + implicit_match = db._repoman_iuse_implicit_cnstr(self.cpv, self._metadata) usealiases = self.root_config.settings._use_manager.getUseAliases(self) self.iuse = self._iuse(self, self._metadata["IUSE"].split(), implicit_match, usealiases, self.eapi) diff --git a/pym/portage/dbapi/__init__.py b/pym/portage/dbapi/__init__.py index d320cc75f..61d301839 100644 --- a/pym/portage/dbapi/__init__.py +++ b/pym/portage/dbapi/__init__.py @@ -216,6 +216,22 @@ class dbapi(object): yield cpv + def _repoman_iuse_implicit_cnstr(self, pkg, metadata): + """ + In repoman's version of _iuse_implicit_cnstr, account for modifications + of the self.settings reference between calls, and treat all flags as + valid for the empty profile because it does not have any implicit IUSE + settings. See bug 660982. + """ + eapi_attrs = _get_eapi_attrs(metadata["EAPI"]) + if eapi_attrs.iuse_effective: + iuse_implicit_match = lambda flag: (True if not self.settings.profile_path + else self.settings._iuse_effective_match(flag)) + else: + iuse_implicit_match = lambda flag: (True if not self.settings.profile_path + else self.settings._iuse_implicit_match(flag)) + return iuse_implicit_match + def _iuse_implicit_cnstr(self, pkg, metadata): """ Construct a callable that checks if a given USE flag should
[gentoo-commits] proj/portage:master commit in: pym/_emerge/, pym/portage/dbapi/, pym/portage/tests/ebuild/, ...
commit: 90fa156df0e6ef4fa9ef1a80c495511f4630de86 Author: Zac Medico gentoo org> AuthorDate: Fri Apr 20 15:21:58 2018 + Commit: Zac Medico gentoo org> CommitDate: Fri Apr 20 15:50:43 2018 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=90fa156d EbuildBuildDir: remove synchronous unlock method (bug 614108) The synchronous unlock method can trigger event loop recursion if the event loop is already running, which is incompatible with asyncio's default event loop. Therefore, migrate the last consumers to use the async_unlock method, and remove the synchronous unlock method. Bug: https://bugs.gentoo.org/614108 Bug: https://bugs.gentoo.org/649588 pym/_emerge/EbuildBuildDir.py | 21 - pym/_emerge/Scheduler.py| 2 +- pym/portage/dbapi/vartree.py| 3 ++- pym/portage/package/ebuild/doebuild.py | 9 ++--- pym/portage/tests/ebuild/test_ipc_daemon.py | 2 +- 5 files changed, 10 insertions(+), 27 deletions(-) diff --git a/pym/_emerge/EbuildBuildDir.py b/pym/_emerge/EbuildBuildDir.py index 1f1385a3b..69f694992 100644 --- a/pym/_emerge/EbuildBuildDir.py +++ b/pym/_emerge/EbuildBuildDir.py @@ -84,27 +84,6 @@ class EbuildBuildDir(SlotObject): except OSError: pass - def unlock(self): - if self._lock_obj is None: - return - - # Keep this legacy implementation until all consumers have migrated - # to async_unlock, since run_until_complete(self.async_unlock()) - # would add unwanted event loop recursion here. - self._lock_obj.unlock() - self._lock_obj = None - self.locked = False - self.settings.pop('PORTAGE_BUILDDIR_LOCKED', None) - catdir_lock = AsynchronousLock(path=self._catdir, scheduler=self.scheduler) - catdir_lock.start() - if catdir_lock.wait() == os.EX_OK: - try: - os.rmdir(self._catdir) - except OSError: - pass - finally: - catdir_lock.unlock() - def async_unlock(self): """ Release the lock asynchronously. Release notification is available diff --git a/pym/_emerge/Scheduler.py b/pym/_emerge/Scheduler.py index eb1cd0108..a248f5974 100644 --- a/pym/_emerge/Scheduler.py +++ b/pym/_emerge/Scheduler.py @@ -911,7 +911,7 @@ class Scheduler(PollScheduler): clean_phase.start() clean_phase.wait() - build_dir.unlock() + sched_iface.run_until_complete(build_dir.async_unlock()) if failures: return FAILURE diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py index c274248e3..8ad6957a3 100644 --- a/pym/portage/dbapi/vartree.py +++ b/pym/portage/dbapi/vartree.py @@ -2199,7 +2199,8 @@ class dblink(object): retval = phase.wait() finally: if builddir_lock is not None: - builddir_lock.unlock() + scheduler.run_until_complete( + builddir_lock.async_unlock()) if log_path is not None: diff --git a/pym/portage/package/ebuild/doebuild.py b/pym/portage/package/ebuild/doebuild.py index 8436c0b10..bdcdfbe87 100644 --- a/pym/portage/package/ebuild/doebuild.py +++ b/pym/portage/package/ebuild/doebuild.py @@ -819,7 +819,8 @@ def doebuild(myebuild, mydo, _unused=DeprecationWarning, settings=None, debug=0, fd_pipes=fd_pipes, returnpid=returnpid) finally: if builddir_lock is not None: - builddir_lock.unlock() + builddir_lock.scheduler.run_until_complete( + builddir_lock.async_unlock()) # get possible slot information from the deps file if mydo == "depend": @@ -943,7 +944,8 @@ def doebuild(myebuild, mydo, _unused=DeprecationWarning, settings=None, debug=0, _spawn_phase("clean", mysettings) finally: if builddir_lock is not None: - builddir_lock.unlock() + builddir_lock.scheduler.run_until_complete( +
[gentoo-commits] proj/portage:master commit in: pym/_emerge/, pym/portage/dbapi/
commit: dfa317d0b8572a6c463ad5e778a8ca4633086f1b Author: Zac Medico gentoo org> AuthorDate: Sun Mar 26 23:54:04 2017 + Commit: Zac Medico gentoo org> CommitDate: Mon Mar 27 02:07:23 2017 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=dfa317d0 emerge: use asyncio interfaces for spinner during owner lookup (bug 591760) X-Gentoo-bug: 591760 X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=591760 Acked-by: Brian Dolbec gentoo.org> pym/_emerge/depgraph.py | 13 - pym/portage/dbapi/vartree.py | 22 +- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index 7c9130b38..04e724d8d 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -3668,17 +3668,20 @@ class depgraph(object): def select_files(self, args): # Use the global event loop for spinner progress # indication during file owner lookups (bug #461412). - spinner_id = None + def spinner_cb(): + self._frozen_config.spinner.update() + spinner_cb.handle = self._event_loop.call_soon(spinner_cb) + + spinner_cb.handle = None try: spinner = self._frozen_config.spinner if spinner is not None and \ spinner.update is not spinner.update_quiet: - spinner_id = self._event_loop.idle_add( - self._frozen_config.spinner.update) + spinner_cb.handle = self._event_loop.call_soon(spinner_cb) return self._select_files(args) finally: - if spinner_id is not None: - self._event_loop.source_remove(spinner_id) + if spinner_cb.handle is not None: + spinner_cb.handle.cancel() def _select_files(self, myfiles): """Given a list of .tbz2s, .ebuilds sets, and deps, populate diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py index c421dc50b..7c8f150bb 100644 --- a/pym/portage/dbapi/vartree.py +++ b/pym/portage/dbapi/vartree.py @@ -1369,32 +1369,28 @@ class vardbapi(dbapi): global_event_loop() or EventLoop(main=False)) root = self._vardb._eroot - def search_pkg(cpv): + def search_pkg(cpv, search_future): dblnk = self._vardb._dblink(cpv) + results = [] for path, name, is_basename in path_info_list: if is_basename: for p in dblnk._contents.keys(): if os.path.basename(p) == name: - search_pkg.results.append((dblnk, + results.append((dblnk, dblnk._contents.unmap_key( p)[len(root):])) else: key = dblnk._match_contents(path) if key is not False: - search_pkg.results.append( + results.append( (dblnk, key[len(root):])) - search_pkg.complete = True - return False - - search_pkg.results = [] + search_future.set_result(results) for cpv in self._vardb.cpv_all(): - del search_pkg.results[:] - search_pkg.complete = False - event_loop.idle_add(search_pkg, cpv) - while not search_pkg.complete: - event_loop.iteration() - for result in search_pkg.results: + search_future = event_loop.create_future() + event_loop.call_soon(search_pkg, cpv, search_future) + event_loop.run_until_complete(search_future) + for result in search_future.result(): yield result class vartree(object):
[gentoo-commits] proj/portage:master commit in: pym/_emerge/, pym/portage/dbapi/, pym/portage/tests/emerge/
commit: dccd4687999aed1788dfe5c3461523f2b23ca79f Author: Zac Medico gentoo org> AuthorDate: Sun Mar 13 07:12:15 2016 + Commit: Zac Medico gentoo org> CommitDate: Wed May 18 16:11:35 2016 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=dccd4687 dblink: add locks for parallel-install with blockers (bug 576888) For parallel-install, lock package slots of the current package and blocked packages, in order to account for blocked packages being removed or replaced concurrently. Acquire locks in predictable order, preventing deadlocks with competitors that may be trying to acquire overlapping locks. X-Gentoo-Bug: 576888 X-Gentoo-Bug-url: https://bugs.gentoo.org/show_bug.cgi?id=576888 Acked-by: Alexander Berntsen gentoo.org> Acked-by: Brian Dolbec gentoo.org> pym/_emerge/Scheduler.py | 9 +- pym/portage/dbapi/vartree.py | 99 +++- .../emerge/test_emerge_blocker_file_collision.py | 168 + 3 files changed, 267 insertions(+), 9 deletions(-) diff --git a/pym/_emerge/Scheduler.py b/pym/_emerge/Scheduler.py index 20a4e85..97b826a 100644 --- a/pym/_emerge/Scheduler.py +++ b/pym/_emerge/Scheduler.py @@ -586,18 +586,15 @@ class Scheduler(PollScheduler): blocker_db = self._blocker_db[new_pkg.root] - blocker_dblinks = [] + blocked_pkgs = [] for blocking_pkg in blocker_db.findInstalledBlockers(new_pkg): if new_pkg.slot_atom == blocking_pkg.slot_atom: continue if new_pkg.cpv == blocking_pkg.cpv: continue - blocker_dblinks.append(portage.dblink( - blocking_pkg.category, blocking_pkg.pf, blocking_pkg.root, - self.pkgsettings[blocking_pkg.root], treetype="vartree", - vartree=self.trees[blocking_pkg.root]["vartree"])) + blocked_pkgs.append(blocking_pkg) - return blocker_dblinks + return blocked_pkgs def _generate_digests(self): """ diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py index e7effca..6209a86 100644 --- a/pym/portage/dbapi/vartree.py +++ b/pym/portage/dbapi/vartree.py @@ -168,6 +168,7 @@ class vardbapi(dbapi): self._conf_mem_file = self._eroot + CONFIG_MEMORY_FILE self._fs_lock_obj = None self._fs_lock_count = 0 + self._slot_locks = {} if vartree is None: vartree = portage.db[settings['EROOT']]['vartree'] @@ -284,6 +285,38 @@ class vardbapi(dbapi): self._fs_lock_obj = None self._fs_lock_count -= 1 + def _slot_lock(self, slot_atom): + """ + Acquire a slot lock (reentrant). + + WARNING: The varbapi._slot_lock method is not safe to call + in the main process when that process is scheduling + install/uninstall tasks in parallel, since the locks would + be inherited by child processes. In order to avoid this sort + of problem, this method should be called in a subprocess + (typically spawned by the MergeProcess class). + """ + lock, counter = self._slot_locks.get(slot_atom, (None, 0)) + if lock is None: + lock_path = self.getpath("%s:%s" % (slot_atom.cp, slot_atom.slot)) + ensure_dirs(os.path.dirname(lock_path)) + lock = lockfile(lock_path, wantnewlockfile=True) + self._slot_locks[slot_atom] = (lock, counter + 1) + + def _slot_unlock(self, slot_atom): + """ + Release a slot lock (or decrementing recursion level). + """ + lock, counter = self._slot_locks.get(slot_atom, (None, 0)) + if lock is None: + raise AssertionError("not locked") + counter -= 1 + if counter == 0: + unlockfile(lock) + del self._slot_locks[slot_atom] + else: + self._slot_locks[slot_atom] = (lock, counter) + def _bump_mtime(self, cpv): """ This is called before an after any modifications, so that consumers @@ -1590,6 +1623,7 @@ class dblink(object): # compliance with RESTRICT=preserve-libs. self._preserve_libs = "preserve-libs" in mysettings.features self._contents = ContentsCaseSensitivityManager(self) + self._slot_locks = [] def __hash__(self): return hash(self._hash_key) @@ -1623,6 +1657,58 @@ class dblink(object): def unl
[gentoo-commits] proj/portage:master commit in: pym/_emerge/, pym/portage/dbapi/
commit: 89a48c206f007d4b1e323c089842cd6475c1eea2 Author: Zac Medico gentoo org> AuthorDate: Fri Apr 24 16:25:45 2015 + Commit: Zac Medico gentoo org> CommitDate: Fri Apr 24 17:54:24 2015 + URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=89a48c20 VdbMetadataDelta.applyDelta: remove replaced versions (bug 547532) Since commit d800d224ab38c0f524d3fe858ebe201cbfa903c1, emerge --search could randomly report incorrect results for the installed version due to the replaced version of a given slot remaining in the cache. Fixes: d800d224ab38 ("Log changes between vdb_metadata.pickle updates") X-Gentoo-Bug: 547532 X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=547532 Acked-by: Brian Dolbec gentoo.org> pym/_emerge/search.py | 10 -- pym/portage/dbapi/_VdbMetadataDelta.py | 22 +- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/pym/_emerge/search.py b/pym/_emerge/search.py index e7f6f44..5a8143c 100644 --- a/pym/_emerge/search.py +++ b/pym/_emerge/search.py @@ -1,4 +1,4 @@ -# Copyright 1999-2014 Gentoo Foundation +# Copyright 1999-2015 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 from __future__ import unicode_literals @@ -442,7 +442,13 @@ class search(object): def getInstallationStatus(self,package): installed_package = self._vardb.match(package) if installed_package: - installed_package = installed_package[-1] + try: + self._vardb.match_unordered + except AttributeError: + installed_package = installed_package[-1] + else: + installed_package = portage.best(installed_package) + else: installed_package = "" result = "" diff --git a/pym/portage/dbapi/_VdbMetadataDelta.py b/pym/portage/dbapi/_VdbMetadataDelta.py index 3e3ff18..2dbb07a 100644 --- a/pym/portage/dbapi/_VdbMetadataDelta.py +++ b/pym/portage/dbapi/_VdbMetadataDelta.py @@ -1,4 +1,4 @@ -# Copyright 2014 Gentoo Foundation +# Copyright 2014-2015 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 import errno @@ -8,6 +8,7 @@ import os from portage import _encodings from portage.util import atomic_ofstream +from portage.versions import cpv_getkey class VdbMetadataDelta(object): @@ -138,10 +139,12 @@ class VdbMetadataDelta(object): def applyDelta(self, data): packages = self._vardb._aux_cache["packages"] + added_slots = {} for delta in data["deltas"]: cpv = delta["package"] + "-" + delta["version"] event = delta["event"] if event == "add": + added_slots[cpv] = delta # Use aux_get to populate the cache # for this cpv. if cpv not in packages: @@ -151,3 +154,20 @@ class VdbMetadataDelta(object): pass elif event == "remove": packages.pop(cpv, None) + + # Remove replaced versions from updated slots + for cached_cpv, (mtime, metadata) in list(packages.items()): + if cached_cpv in added_slots: + continue + replaced = False + for cpv, delta in added_slots.items(): + if (cached_cpv.startswith(delta["package"]) and + metadata.get("SLOT") == delta["slot"] and + cpv_getkey(cached_cpv) == delta["package"]): + replaced = True + break + if replaced: + del packages[cached_cpv] + del added_slots[cpv] + if not added_slots: + break
[gentoo-commits] proj/portage:master commit in: pym/_emerge/, pym/portage/dbapi/
commit: 206efe5f6341bce99a5e9994a0458c304513b2c3 Author: Zac Medico gentoo org> AuthorDate: Thu Nov 20 12:38:59 2014 + Commit: Zac Medico gentoo org> CommitDate: Mon Nov 24 07:38:51 2014 + URL: http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=206efe5f emerge: check for writable PKGDIR (490732) 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 Acked-by: Alexander Berntsen gentoo.org> --- 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, **k