commit:     0a5692bd4f4ab4a54daf2ce09112617cbc21c9ad
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Sun Apr 22 22:22:20 2018 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Mon Apr 23 18:39:47 2018 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=0a5692bd

EbuildFetcher: add async_already_fetched method (bug 653810)

Add an async_already_fetched method to replace the synchronous
already_fetched method, and use it to prevent event loop recursion.

Bug: https://bugs.gentoo.org/653810
Reviewed-by: Brian Dolbec <dolsen <AT> gentoo.org>

 pym/_emerge/EbuildBuild.py   |  8 +++++++-
 pym/_emerge/EbuildFetcher.py | 30 ++++++++++++++++++++++++------
 2 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/pym/_emerge/EbuildBuild.py b/pym/_emerge/EbuildBuild.py
index 8ad8bcae9..9651bd419 100644
--- a/pym/_emerge/EbuildBuild.py
+++ b/pym/_emerge/EbuildBuild.py
@@ -216,8 +216,14 @@ class EbuildBuild(CompositeTask):
                        logfile=self.settings.get('PORTAGE_LOG_FILE'),
                        pkg=self.pkg, scheduler=self.scheduler)
 
+               self._start_task(AsyncTaskFuture(
+                       future=fetcher.async_already_fetched(self.settings)),
+                       functools.partial(self._start_fetch, fetcher))
+
+       def _start_fetch(self, fetcher, already_fetched_task):
+               self._assert_current(already_fetched_task)
                try:
-                       already_fetched = fetcher.already_fetched(self.settings)
+                       already_fetched = already_fetched_task.future.result()
                except portage.exception.InvalidDependString as e:
                        msg_lines = []
                        msg = "Fetch failed for '%s' due to invalid SRC_URI: 
%s" % \

diff --git a/pym/_emerge/EbuildFetcher.py b/pym/_emerge/EbuildFetcher.py
index 8f6cc60fe..589eda85d 100644
--- a/pym/_emerge/EbuildFetcher.py
+++ b/pym/_emerge/EbuildFetcher.py
@@ -28,7 +28,7 @@ class EbuildFetcher(CompositeTask):
                CompositeTask.__init__(self, **kwargs)
                self._fetcher_proc = _EbuildFetcherProcess(**kwargs)
 
-       def already_fetched(self, settings):
+       def async_already_fetched(self, settings):
                """
                Returns True if all files already exist locally and have correct
                digests, otherwise return False. When returning True, 
appropriate
@@ -38,7 +38,7 @@ class EbuildFetcher(CompositeTask):
                such messages. This will raise InvalidDependString if SRC_URI is
                invalid.
                """
-               return self._fetcher_proc.already_fetched(settings)
+               return self._fetcher_proc.async_already_fetched(settings)
 
        def _start(self):
                self._start_task(
@@ -68,11 +68,29 @@ class _EbuildFetcherProcess(ForkProcess):
        __slots__ = ("config_pool", "ebuild_path", "fetchonly", "fetchall",
                "pkg", "prefetch", "_digests", "_manifest", "_settings", 
"_uri_map")
 
-       def already_fetched(self, settings):
-               uri_map = 
self.scheduler.run_until_complete(self._async_uri_map())
-               if not uri_map:
-                       return True
+       def async_already_fetched(self, settings):
+               result = self.scheduler.create_future()
+
+               def uri_map_done(uri_map_future):
+                       if uri_map_future.exception() is not None or 
result.cancelled():
+                               if not result.cancelled():
+                                       
result.set_exception(uri_map_future.exception())
+                               return
+
+                       uri_map = uri_map_future.result()
+                       if uri_map:
+                               result.set_result(
+                                       self._check_already_fetched(settings, 
uri_map))
+                       else:
+                               result.set_result(True)
+
+               uri_map_future = self._async_uri_map()
+               result.add_done_callback(lambda result:
+                       aux_get_future.cancel() if result.cancelled() else None)
+               uri_map_future.add_done_callback(uri_map_done)
+               return result
 
+       def _check_already_fetched(self, settings, uri_map):
                digests = self._get_digests()
                distdir = settings["DISTDIR"]
                allow_missing = self._get_manifest().allow_missing

Reply via email to