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 0694cefa849f801cbcfb1df3e7ad2e8c827f4201
Author: Jürg Billeter <j...@bitron.ch>
AuthorDate: Fri Aug 8 14:04:32 2025 +0200

    Store sandbox state in Artifact proto
    
    This is stored only when also storing the build tree. It is used to
    configure the sandbox for `bst shell --use-buildtree`.
    
    This is required for elements that create subsandboxes as part of
    `configure_sandbox()`.
---
 src/buildstream/_artifact.py      | 30 ++++++++++++++++++++++++++++++
 src/buildstream/_artifactcache.py | 10 ++++++++++
 src/buildstream/element.py        | 10 +++++++---
 3 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/src/buildstream/_artifact.py b/src/buildstream/_artifact.py
index 7ccc61c6a..c06603559 100644
--- a/src/buildstream/_artifact.py
+++ b/src/buildstream/_artifact.py
@@ -200,6 +200,7 @@ class Artifact:
     #    variables (Variables): The element's Variables
     #    environment (dict): dict of the element's environment variables
     #    sandboxconfig (SandboxConfig): The element's SandboxConfig
+    #    buildsandbox (Sandbox): The element's configured build sandbox
     #
     def cache(
         self,
@@ -213,6 +214,7 @@ class Artifact:
         variables,
         environment,
         sandboxconfig,
+        buildsandbox,
     ):
 
         context = self._context
@@ -317,6 +319,19 @@ class Artifact:
             rootvdir._import_files_internal(buildrootvdir, 
properties=properties, collect_result=False)
             artifact.buildroot.CopyFrom(rootvdir._get_digest())
 
+        if buildsandbox is not None:
+            sandbox_env = buildsandbox._get_configured_environment()
+            if sandbox_env:
+                for key, value in sorted(sandbox_env.items()):
+                    artifact.buildsandbox.environment.add(name=key, 
value=value)
+
+            artifact.buildsandbox.working_directory = 
buildsandbox._get_work_directory()
+
+            for subsandbox in buildsandbox._get_subsandboxes():
+                vdir = subsandbox.get_virtual_directory()
+                digest = artifact.buildsandbox.subsandbox_digests.add()
+                digest.CopyFrom(vdir._get_digest())
+
         os.makedirs(os.path.dirname(os.path.join(self._artifactdir, 
element.get_artifact_name())), exist_ok=True)
         keys = utils._deduplicate([self._cache_key, self._weak_cache_key])
         for key in keys:
@@ -681,6 +696,21 @@ class Artifact:
 
         return True
 
+    def configure_sandbox(self, sandbox):
+        artifact = self._get_proto()
+
+        if artifact.buildsandbox and artifact.buildsandbox.environment:
+            env = {}
+            for env_var in artifact.buildsandbox.environment:
+                env[env_var.name] = env_var.value
+        else:
+            env = self.load_environment()
+
+        sandbox.set_environment(env)
+
+        if artifact.buildsandbox and artifact.buildsandbox.working_directory:
+            sandbox.set_work_directory(artifact.buildsandbox.working_directory)
+
     #  load_proto()
     #
     # Returns:
diff --git a/src/buildstream/_artifactcache.py 
b/src/buildstream/_artifactcache.py
index a32d0ee62..9f4062449 100644
--- a/src/buildstream/_artifactcache.py
+++ b/src/buildstream/_artifactcache.py
@@ -303,6 +303,10 @@ class ArtifactCache(AssetCache):
                 except FileNotFoundError:
                     pass
 
+            if artifact_proto.buildsandbox:
+                for subsandbox_digest in 
artifact_proto.buildsandbox.subsandbox_digests:
+                    self.cas._send_directory(remote, subsandbox_digest)
+
             digests = [artifact_digest, artifact_proto.low_diversity_meta, 
artifact_proto.high_diversity_meta]
 
             if str(artifact_proto.public_data):
@@ -361,6 +365,9 @@ class ArtifactCache(AssetCache):
             referenced_directories.append(artifact_proto.sources)
         if artifact_proto.buildroot:
             referenced_directories.append(artifact_proto.buildroot)
+        if artifact_proto.buildsandbox:
+            for subsandbox_digest in 
artifact_proto.buildsandbox.subsandbox_digests:
+                referenced_directories.append(subsandbox_digest)
 
         referenced_blobs = [artifact_proto.low_diversity_meta, 
artifact_proto.high_diversity_meta] + [
             log_file.digest for log_file in artifact_proto.logs
@@ -419,6 +426,9 @@ class ArtifactCache(AssetCache):
                     self.cas.fetch_directory(remote, artifact.buildtree)
                 if str(artifact.buildroot):
                     self.cas.fetch_directory(remote, artifact.buildroot)
+                if artifact.buildsandbox:
+                    for subsandbox_digest in 
artifact.buildsandbox.subsandbox_digests:
+                        self.cas.fetch_directory(remote, subsandbox_digest)
 
             digests = [artifact.low_diversity_meta, 
artifact.high_diversity_meta]
             if str(artifact.public_data):
diff --git a/src/buildstream/element.py b/src/buildstream/element.py
index a9d12fbde..403c96ded 100644
--- a/src/buildstream/element.py
+++ b/src/buildstream/element.py
@@ -1440,18 +1440,21 @@ class Element(Plugin):
         # pylint: disable-next=contextmanager-generator-missing-cleanup
         with self.__sandbox(config=self.__sandbox_config, allow_remote=False) 
as sandbox:
 
-            # Configure always comes first, and we need it.
-            self.__configure_sandbox(sandbox)
-
             if usebuildtree:
+                # Configure the sandbox from artifact metadata
+                self.__artifact.configure_sandbox(sandbox)
+
                 # Use the cached buildroot directly
                 buildrootvdir = self.__artifact.get_buildroot()
                 sandbox_vroot = sandbox.get_virtual_directory()
                 sandbox_vroot._import_files_internal(buildrootvdir, 
collect_result=False)
             elif shell and scope == _Scope.BUILD:
+                self.__configure_sandbox(sandbox)
                 # Stage what we need
                 self.__stage(sandbox)
             else:
+                self.__configure_sandbox(sandbox)
+
                 # Stage deps in the sandbox root
                 with self.timed_activity("Staging dependencies", 
silent_nested=True), self.__collect_overlaps(sandbox):
                     self._stage_dependency_artifacts(sandbox, scope)
@@ -1787,6 +1790,7 @@ class Element(Plugin):
                 variables=self.__variables,
                 environment=self.__environment,
                 sandboxconfig=self.__sandbox_config,
+                buildsandbox=sandbox if buildrootvdir else None,
             )
 
         if collect is not None and collectvdir is None:

Reply via email to