This is an automated email from the ASF dual-hosted git repository. akitouni pushed a commit to branch abderrahim/nested-reapi in repository https://gitbox.apache.org/repos/asf/buildstream.git
commit 0bf2d064db52211124c891c9d0daf6a36ba7bf7b Author: Jürg Billeter <j...@bitron.ch> AuthorDate: Fri Jul 18 11:57:24 2025 +0200 element.py: Support per-sandbox overlap collector With the introduction of subsandboxes, a single overlap collector is no longer sufficient. --- src/buildstream/_elementproxy.py | 5 +++-- src/buildstream/element.py | 33 +++++++++++++++++++-------------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/buildstream/_elementproxy.py b/src/buildstream/_elementproxy.py index 861bc9a15..3425b6cc3 100644 --- a/src/buildstream/_elementproxy.py +++ b/src/buildstream/_elementproxy.py @@ -104,9 +104,10 @@ class ElementProxy(PluginProxy): owner = cast("Element", self._owner) element = cast("Element", self._plugin) - assert owner._overlap_collector is not None, "Attempted to stage artifacts outside of Element.stage()" + overlap_collector = owner._overlap_collectors.get(sandbox) + assert overlap_collector is not None, "Attempted to stage artifacts outside of Element.stage()" - with owner._overlap_collector.session(action, path): + with overlap_collector.session(action, path): result = element._stage_artifact( sandbox, path=path, action=action, include=include, exclude=exclude, orphans=orphans, owner=owner ) diff --git a/src/buildstream/element.py b/src/buildstream/element.py index f267ce7e3..ecc4de77a 100644 --- a/src/buildstream/element.py +++ b/src/buildstream/element.py @@ -254,7 +254,7 @@ class Element(Plugin): # Internal instance properties # self._depth = None # Depth of Element in its current dependency graph - self._overlap_collector = None # type: Optional[OverlapCollector] + self._overlap_collectors: Dict[Sandbox, OverlapCollector] = {} # Active overlap collector per sandbox self._description = load_element.description or "" # type: str # @@ -642,7 +642,8 @@ class Element(Plugin): :func:`Element.stage_dependency_artifacts() <buildstream.element.Element.stage_dependency_artifacts>` instead. """ - assert self._overlap_collector is not None, "Attempted to stage artifacts outside of Element.stage()" + overlap_collector = self._overlap_collectors.get(sandbox) + assert overlap_collector is not None, "Attempted to stage artifacts outside of Element.stage()" # # The public API can only be called on the implementing plugin itself. @@ -650,7 +651,7 @@ class Element(Plugin): # ElementProxy calls to stage_artifact() are routed directly to _stage_artifact(), # and the ElementProxy takes care of starting and ending the OverlapCollector session. # - with self._overlap_collector.session(action, path): + with overlap_collector.session(action, path): result = self._stage_artifact( sandbox, path=path, action=action, include=include, exclude=exclude, orphans=orphans ) @@ -692,9 +693,10 @@ class Element(Plugin): Raises: (:class:`.ElementError`): if forbidden overlaps occur. """ - assert self._overlap_collector is not None, "Attempted to stage artifacts outside of Element.stage()" + overlap_collector = self._overlap_collectors.get(sandbox) + assert overlap_collector is not None, "Attempted to stage artifacts outside of Element.stage()" - with self._overlap_collector.session(action, path): + with overlap_collector.session(action, path): for dep in self.dependencies(selection): dep._stage_artifact(sandbox, path=path, include=include, exclude=exclude, orphans=orphans, owner=self) @@ -962,7 +964,8 @@ class Element(Plugin): ) -> FileListResult: owner = owner or self - assert owner._overlap_collector is not None, "Attempted to stage artifacts outside of Element.stage()" + overlap_collector = owner._overlap_collectors.get(sandbox) + assert overlap_collector is not None, "Attempted to stage artifacts outside of Element.stage()" if not self._cached(): detail = ( @@ -989,7 +992,7 @@ class Element(Plugin): result = vstagedir._import_files_internal(files_vdir, filter_callback=split_filter) assert result is not None - owner._overlap_collector.collect_stage_result(self, result) + overlap_collector.collect_stage_result(self, result) return result @@ -1013,7 +1016,7 @@ class Element(Plugin): # occur. # def _stage_dependency_artifacts(self, sandbox, scope, *, path=None, include=None, exclude=None, orphans=True): - with self._overlap_collector.session(OverlapAction.WARNING, path): + with self._overlap_collectors[sandbox].session(OverlapAction.WARNING, path): for dep in self._dependencies(scope): dep._stage_artifact(sandbox, path=path, include=include, exclude=exclude, orphans=orphans, owner=self) @@ -1435,7 +1438,7 @@ class Element(Plugin): self.__stage(sandbox) else: # Stage deps in the sandbox root - with self.timed_activity("Staging dependencies", silent_nested=True), self.__collect_overlaps(): + with self.timed_activity("Staging dependencies", silent_nested=True), self.__collect_overlaps(sandbox): self._stage_dependency_artifacts(sandbox, scope) # Run any integration commands provided by the dependencies @@ -2703,7 +2706,7 @@ class Element(Plugin): def __stage(self, sandbox): # Enable the overlap collector during the staging process - with self.__collect_overlaps(): + with self.__collect_overlaps(sandbox): self.stage(sandbox) # __preflight(): @@ -2806,10 +2809,12 @@ class Element(Plugin): # this context manager. # @contextmanager - def __collect_overlaps(self): - self._overlap_collector = OverlapCollector(self) - yield - self._overlap_collector = None + def __collect_overlaps(self, sandbox): + self._overlap_collectors[sandbox] = OverlapCollector(self) + try: + yield + finally: + del self._overlap_collectors[sandbox] # __sandbox(): #