diff options
Diffstat (limited to 'pym/_emerge/EbuildFetcher.py')
-rw-r--r-- | pym/_emerge/EbuildFetcher.py | 120 |
1 files changed, 105 insertions, 15 deletions
diff --git a/pym/_emerge/EbuildFetcher.py b/pym/_emerge/EbuildFetcher.py index c076288cc..066678748 100644 --- a/pym/_emerge/EbuildFetcher.py +++ b/pym/_emerge/EbuildFetcher.py @@ -14,24 +14,97 @@ from portage import _encodings from portage import _unicode_encode from portage import _unicode_decode from portage.elog.messages import eerror -from portage.package.ebuild.fetch import fetch +from portage.package.ebuild.fetch import _check_distfile, fetch from portage.util._pty import _create_pty_or_pipe class EbuildFetcher(SpawnProcess): - __slots__ = ("config_pool", "fetchonly", "fetchall", "pkg", "prefetch") + \ + __slots__ = ("config_pool", "ebuild_path", "fetchonly", "fetchall", + "pkg", "prefetch") + \ ("_digests", "_settings", "_uri_map") + def already_fetched(self, settings): + """ + Returns True if all files are already exist locally and have correct + digests, otherwise return False. When returning True, appropriate + digest checking messages are produced for display and/or logging. + When returning False, no messages are produced, since we assume + that a fetcher process will later be executed in order to produce + such messages. This will raise InvalidDependString if SRC_URI is + invalid. + """ + + uri_map = self._get_uri_map() + if not uri_map: + return True + + digests = self._get_digests() + distdir = settings["DISTDIR"] + allow_missing = "allow-missing-manifests" in settings.features + + for filename in uri_map: + # Use stat rather than lstat since fetch() creates + # symlinks when PORTAGE_RO_DISTDIRS is used. + try: + st = os.stat(os.path.join(distdir, filename)) + except OSError: + return False + if st.st_size == 0: + return False + expected_size = digests.get(filename, {}).get('size') + if expected_size is None: + continue + if st.st_size != expected_size: + return False + + stdout_orig = sys.stdout + stderr_orig = sys.stderr + global_havecolor = portage.output.havecolor + out = io.StringIO() + eout = portage.output.EOutput() + eout.quiet = settings.get("PORTAGE_QUIET") == "1" + success = True + try: + sys.stdout = out + sys.stderr = out + if portage.output.havecolor: + portage.output.havecolor = not self.background + + for filename in uri_map: + mydigests = digests.get(filename) + if mydigests is None: + if not allow_missing: + success = False + break + continue + ok, st = _check_distfile(os.path.join(distdir, filename), + mydigests, eout, show_errors=False) + if not ok: + success = False + break + finally: + sys.stdout = stdout_orig + sys.stderr = stderr_orig + portage.output.havecolor = global_havecolor + + if success: + # When returning uncessessfully, no messages are produced, since + # we assume that a fetcher process will later be executed in order + # to produce such messages. + msg = out.getvalue() + if msg: + self.scheduler.output(msg, log_path=self.logfile) + + return success + def _start(self): root_config = self.pkg.root_config portdb = root_config.trees["porttree"].dbapi - ebuild_path = portdb.findname(self.pkg.cpv, myrepo=self.pkg.repo) - if ebuild_path is None: - raise AssertionError("ebuild not found for '%s'" % self.pkg.cpv) + ebuild_path = self._get_ebuild_path() try: - uri_map = self._get_uri_map(portdb, ebuild_path) + uri_map = self._get_uri_map() except portage.exception.InvalidDependString as e: msg_lines = [] msg = "Fetch failed for '%s' due to invalid SRC_URI: %s" % \ @@ -48,9 +121,6 @@ class EbuildFetcher(SpawnProcess): self.wait() return - self._digests = portage.Manifest( - os.path.dirname(ebuild_path), None).getTypeDigests("DIST") - settings = self.config_pool.allocate() settings.setcpv(self.pkg) portage.doebuild_environment(ebuild_path, 'fetch', @@ -75,7 +145,6 @@ class EbuildFetcher(SpawnProcess): settings["NOCOLOR"] = nocolor self._settings = settings - self._uri_map = uri_map SpawnProcess._start(self) # Free settings now since it's no longer needed in @@ -110,7 +179,7 @@ class EbuildFetcher(SpawnProcess): allow_missing = 'allow-missing-manifests' in self._settings.features try: if fetch(self._uri_map, self._settings, fetchonly=self.fetchonly, - digests=copy.deepcopy(self._digests), + digests=copy.deepcopy(self._get_digests()), allow_missing_digests=allow_missing): rval = os.EX_OK except SystemExit: @@ -122,16 +191,37 @@ class EbuildFetcher(SpawnProcess): # finally blocks from earlier in the call stack. See bug #345289. os._exit(rval) - def _get_uri_map(self, portdb, ebuild_path): + def _get_ebuild_path(self): + if self.ebuild_path is not None: + return self.ebuild_path + portdb = self.pkg.root_config.trees["porttree"].dbapi + self.ebuild_path = portdb.findname(self.pkg.cpv, myrepo=self.pkg.repo) + if self.ebuild_path is None: + raise AssertionError("ebuild not found for '%s'" % self.pkg.cpv) + return self.ebuild_path + + def _get_digests(self): + if self._digests is not None: + return self._digests + self._digests = portage.Manifest(os.path.dirname( + self._get_ebuild_path()), None).getTypeDigests("DIST") + return self._digests + + def _get_uri_map(self): """ This can raise InvalidDependString from portdbapi.getFetchMap(). """ - pkgdir = os.path.dirname(ebuild_path) + if self._uri_map is not None: + return self._uri_map + pkgdir = os.path.dirname(self._get_ebuild_path()) mytree = os.path.dirname(os.path.dirname(pkgdir)) use = None if not self.fetchall: use = self.pkg.use.enabled - return portdb.getFetchMap(self.pkg.cpv, useflags=use, mytree=mytree) + portdb = self.pkg.root_config.trees["porttree"].dbapi + self._uri_map = portdb.getFetchMap(self.pkg.cpv, + useflags=use, mytree=mytree) + return self._uri_map def _prefetch_size_ok(self, uri_map, settings, ebuild_path): distdir = settings["DISTDIR"] @@ -148,7 +238,7 @@ class EbuildFetcher(SpawnProcess): return False sizes[filename] = st.st_size - digests = self._digests + digests = self._get_digests() for filename, actual_size in sizes.items(): size = digests.get(filename, {}).get('size') if size is None: |