| # Copyright 2013 Gentoo Foundation |
| # Distributed under the terms of the GNU General Public License v2 |
| |
| from portage import os |
| from portage.checksum import (_apply_hash_filter, |
| _filter_unaccelarated_hashes, _hash_filter) |
| from portage.dep import use_reduce |
| from portage.exception import PortageException |
| from .FetchTask import FetchTask |
| |
| class FetchIterator(object): |
| |
| def __init__(self, config): |
| self._config = config |
| self._log_failure = config.log_failure |
| |
| def _iter_every_cp(self): |
| # List categories individually, in order to start yielding quicker, |
| # and in order to reduce latency in case of a signal interrupt. |
| cp_all = self._config.portdb.cp_all |
| for category in sorted(self._config.portdb.categories): |
| for cp in cp_all(categories=(category,)): |
| yield cp |
| |
| def __iter__(self): |
| |
| portdb = self._config.portdb |
| get_repo_for_location = portdb.repositories.get_repo_for_location |
| file_owners = self._config.file_owners |
| file_failures = self._config.file_failures |
| restrict_mirror_exemptions = self._config.restrict_mirror_exemptions |
| |
| hash_filter = _hash_filter( |
| portdb.settings.get("PORTAGE_CHECKSUM_FILTER", "")) |
| if hash_filter.transparent: |
| hash_filter = None |
| |
| for cp in self._iter_every_cp(): |
| |
| for tree in portdb.porttrees: |
| |
| # Reset state so the Manifest is pulled once |
| # for this cp / tree combination. |
| digests = None |
| repo_config = get_repo_for_location(tree) |
| |
| for cpv in portdb.cp_list(cp, mytree=tree): |
| |
| try: |
| restrict, = portdb.aux_get(cpv, ("RESTRICT",), |
| mytree=tree) |
| except (KeyError, PortageException) as e: |
| self._log_failure("%s\t\taux_get exception %s" % |
| (cpv, e)) |
| continue |
| |
| # Here we use matchnone=True to ignore conditional parts |
| # of RESTRICT since they don't apply unconditionally. |
| # Assume such conditionals only apply on the client side. |
| try: |
| restrict = frozenset(use_reduce(restrict, |
| flat=True, matchnone=True)) |
| except PortageException as e: |
| self._log_failure("%s\t\tuse_reduce exception %s" % |
| (cpv, e)) |
| continue |
| |
| if "fetch" in restrict: |
| continue |
| |
| try: |
| uri_map = portdb.getFetchMap(cpv) |
| except PortageException as e: |
| self._log_failure("%s\t\tgetFetchMap exception %s" % |
| (cpv, e)) |
| continue |
| |
| if not uri_map: |
| continue |
| |
| if "mirror" in restrict: |
| skip = False |
| if restrict_mirror_exemptions is not None: |
| new_uri_map = {} |
| for filename, uri_tuple in uri_map.items(): |
| for uri in uri_tuple: |
| if uri[:9] == "mirror://": |
| i = uri.find("/", 9) |
| if i != -1 and uri[9:i].strip("/") in \ |
| restrict_mirror_exemptions: |
| new_uri_map[filename] = uri_tuple |
| break |
| if new_uri_map: |
| uri_map = new_uri_map |
| else: |
| skip = True |
| else: |
| skip = True |
| |
| if skip: |
| continue |
| |
| # Parse Manifest for this cp if we haven't yet. |
| if digests is None: |
| try: |
| digests = repo_config.load_manifest( |
| os.path.join(repo_config.location, cp) |
| ).getTypeDigests("DIST") |
| except (EnvironmentError, PortageException) as e: |
| for filename in uri_map: |
| self._log_failure( |
| "%s\t%s\tManifest exception %s" % |
| (cpv, filename, e)) |
| file_failures[filename] = cpv |
| continue |
| |
| if not digests: |
| for filename in uri_map: |
| self._log_failure("%s\t%s\tdigest entry missing" % |
| (cpv, filename)) |
| file_failures[filename] = cpv |
| continue |
| |
| for filename, uri_tuple in uri_map.items(): |
| file_digests = digests.get(filename) |
| if file_digests is None: |
| self._log_failure("%s\t%s\tdigest entry missing" % |
| (cpv, filename)) |
| file_failures[filename] = cpv |
| continue |
| if filename in file_owners: |
| continue |
| file_owners[filename] = cpv |
| |
| file_digests = \ |
| _filter_unaccelarated_hashes(file_digests) |
| if hash_filter is not None: |
| file_digests = _apply_hash_filter( |
| file_digests, hash_filter) |
| |
| yield FetchTask(cpv=cpv, |
| background=True, |
| digests=file_digests, |
| distfile=filename, |
| restrict=restrict, |
| uri_tuple=uri_tuple, |
| config=self._config) |