On Sat, 14 Jul 2018 21:05:39 -0700 Zac Medico <zmed...@gentoo.org> wrote:
> 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 > --- > 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: > if isinstance(mytree, basestring): > - mytrees = [mytree] > + repos = > [self.repositories.get_repo_for_location(mytree)] else: > # assume it's iterable > - mytrees = mytree > + repos = > [self.repositories.get_repo_for_location(location) > + for location in mytree] > elif self._better_cache is None: > - mytrees = self.porttrees > + repos = list(self.repositories) > else: > - mytrees = [repo.location for repo in > self._better_cache[mycp]] > - for oroot in mytrees: > + repos = reversed(self._better_cache[mycp]) > + mylist = [] > + for repo in repos: > + oroot = repo.location > try: > file_list = > os.listdir(os.path.join(oroot, mycp)) except OSError: > @@ -986,16 +1002,17 @@ class portdbapi(dbapi): > writemsg(_("\nInvalid > ebuild version: %s\n") % \ os.path.join(oroot, mycp, x), > noiselevel=-1) continue > - > d[_pkg_str(mysplit[0]+"/"+pf, db=self)] = None > - if invalid_category and d: > + > mylist.append(_pkg_str(mysplit[0]+"/"+pf, db=self, repo=repo.name)) > + if invalid_category and mylist: > writemsg(_("\n!!! '%s' has a category that > is not listed in " \ "%setc/portage/categories\n") % \ > (mycp, > self.settings["PORTAGE_CONFIGROOT"]), noiselevel=-1) mylist = [] > - else: > - mylist = list(d) > - # Always sort in ascending order here since it's > handy > - # and the result can be easily cached and reused. > + # Always sort in ascending order here since it's > handy and > + # the result can be easily cached and reused. Since > mylist > + # is initially in ascending order by repo.priority, > stable > + # sort by version produces results in ascending > order by > + # (pkg.version, repo.priority). > self._cpv_sort_ascending(mylist) > if self.frozen and mytree is None: > cachelist = mylist[:] looks fine -- Brian Dolbec <dolsen>