Index: pym/_emerge/__init__.py =================================================================== --- pym/_emerge/__init__.py (revision 10768) +++ pym/_emerge/__init__.py (revision 10775) @@ -20,6 +20,7 @@ except KeyboardInterrupt: sys.exit(1) +import gc import os, stat import platform @@ -1773,6 +1774,15 @@ self._cp_map = {} self._cpv_map = {} + def clear(self): + """ + Remove all packages. + """ + if self._cpv_map: + self._clear_cache() + self._cp_map.clear() + self._cpv_map.clear() + def copy(self): obj = PackageVirtualDbapi(self.settings) obj._match_cache = self._match_cache.copy() @@ -3828,6 +3849,29 @@ retlist.reverse() return retlist + def break_refs(self, mergelist): + """ + Take a mergelist like that returned from self.altlist() and + break any references that lead back to the depgraph. This is + useful if you want to hold references to packages without + also holding the depgraph on the heap. + """ + for node in mergelist: + if not isinstance(node, Package): + continue + + # The visible packages cache has fullfilled it's purpose + # and it's no longer needed, so free the memory. + node.root_config.visible_pkgs.clear() + + if isinstance(node.root_config.trees["vartree"], FakeVartree): + # The FakeVartree references the _package_cache which + # references the depgraph. So that Package instances don't + # hold the depgraph and FakeVartree on the heap, replace + # the FakeVartree reference with the real vartree. + node.root_config.trees["vartree"] = \ + self._trees_orig[node.root]["vartree"] + def _resolve_conflicts(self): if not self._complete_graph(): raise self._unknown_internal_error() @@ -8738,7 +8782,10 @@ mtimedb.filename = None time.sleep(3) # allow the parent to have first fetch mymergelist = mydepgraph.altlist() + mydepgraph.break_refs(mymergelist) del mydepgraph + clear_caches(trees) + retval = mergetask.merge(mymergelist, favorites, mtimedb) merge_count = mergetask.curval else: @@ -8779,7 +8826,10 @@ pkglist = mydepgraph.altlist() mydepgraph.saveNomergeFavorites() + mydepgraph.break_refs(pkglist) del mydepgraph + clear_caches(trees) + mergetask = MergeTask(settings, trees, myopts) retval = mergetask.merge(pkglist, favorites, mtimedb) merge_count = mergetask.curval @@ -8903,6 +8953,14 @@ settings = trees[myroot]["vartree"].settings settings.validate() +def clear_caches(trees): + for d in trees.itervalues(): + d["porttree"].dbapi.melt() + d["porttree"].dbapi._aux_cache.clear() + d["bintree"].dbapi._aux_cache.clear() + d["bintree"].dbapi._clear_cache() + gc.collect() + def load_emerge_config(trees=None): kwargs = {} for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):