summaryrefslogtreecommitdiff
path: root/src/buildstream/_artifactelement.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/buildstream/_artifactelement.py')
-rw-r--r--src/buildstream/_artifactelement.py114
1 files changed, 55 insertions, 59 deletions
diff --git a/src/buildstream/_artifactelement.py b/src/buildstream/_artifactelement.py
index 3dce09202..63bb904fd 100644
--- a/src/buildstream/_artifactelement.py
+++ b/src/buildstream/_artifactelement.py
@@ -1,5 +1,6 @@
#
# Copyright (C) 2019 Bloomberg Finance LP
+# Copyright (C) 2020 Codethink Limited
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -16,17 +17,22 @@
#
# Authors:
# James Ennis <james.ennis@codethink.co.uk>
+# Tristan Van Berkom <tristan.vanberkom@codethink.co.uk>
-from typing import TYPE_CHECKING
+from typing import TYPE_CHECKING, Optional, Dict
+from contextlib import suppress
from . import Element
from . import _cachekey
+from ._artifact import Artifact
+from ._artifactproject import ArtifactProject
from ._exceptions import ArtifactElementError
from ._loader import LoadElement
from .node import Node
if TYPE_CHECKING:
- from typing import Dict
+ from ._context import Context
+ from ._state import _Task
# ArtifactElement()
@@ -40,51 +46,70 @@ if TYPE_CHECKING:
class ArtifactElement(Element):
# A hash of ArtifactElement by ref
- __instantiated_artifacts = {} # type: Dict[str, ArtifactElement]
+ __instantiated_artifacts: Dict[str, "ArtifactElement"] = {}
def __init__(self, context, ref):
- _, element, key = verify_artifact_ref(ref)
+ project_name, element_name, key = verify_artifact_ref(ref)
- self._ref = ref
- self._key = key
+ # At this point we only know the key which was specified on the command line,
+ # so we will pretend all keys are equal.
+ #
+ # If the artifact is cached, then the real keys will be loaded from the
+ # artifact instead.
+ #
+ artifact = Artifact(self, context, strong_key=key, strict_key=key, weak_key=key)
+ project = ArtifactProject(project_name, context)
+ load_element = LoadElement(Node.from_dict({}), element_name, project.loader) # NOTE element has no .bst suffix
- project = context.get_toplevel_project()
- load_element = LoadElement(Node.from_dict({}), element, project.loader) # NOTE element has no .bst suffix
+ super().__init__(context, project, load_element, None, artifact=artifact)
- super().__init__(context, project, load_element, None)
+ ########################################################
+ # Public API #
+ ########################################################
- # _new_from_artifact_name():
+ # new_from_artifact_name():
#
# Recursively instantiate a new ArtifactElement instance, and its
# dependencies from an artifact name
#
# Args:
- # ref (String): The artifact ref
- # context (Context): The Context object
- # task (Task): A task object to report progress to
+ # artifact_name: The artifact name
+ # context: The Context object
+ # task: A task object to report progress to
#
# Returns:
# (ArtifactElement): A newly created Element instance
#
@classmethod
- def _new_from_artifact_name(cls, ref, context, task=None):
+ def new_from_artifact_name(cls, artifact_name: str, context: "Context", task: Optional["_Task"] = None):
- if ref in cls.__instantiated_artifacts:
- return cls.__instantiated_artifacts[ref]
+ # Initial lookup for already loaded artifact.
+ with suppress(KeyError):
+ return cls.__instantiated_artifacts[artifact_name]
- artifact_element = ArtifactElement(context, ref)
- # XXX: We need to call initialize_state as it is responsible for
- # initialising an Element/ArtifactElement's Artifact (__artifact)
- artifact_element._initialize_state()
- cls.__instantiated_artifacts[ref] = artifact_element
+ # Instantiate the element, this can result in having a different
+ # artifact name, if we loaded the artifact by it's weak key then
+ # we will have the artifact loaded via it's strong key.
+ element = ArtifactElement(context, artifact_name)
+ artifact_name = element.get_artifact_name()
- for dep_ref in artifact_element.get_dependency_artifact_names():
- dependency = ArtifactElement._new_from_artifact_name(dep_ref, context, task)
- artifact_element._add_build_dependency(dependency)
+ # Perform a second lookup, avoid loading the same artifact
+ # twice, even if we've loaded it both with weak and strong keys.
+ with suppress(KeyError):
+ return cls.__instantiated_artifacts[artifact_name]
- return artifact_element
+ # Now cache the loaded artifact
+ cls.__instantiated_artifacts[artifact_name] = element
- # _clear_artifact_refs_cache()
+ # Walk the dependencies and load recursively
+ artifact = element._get_artifact()
+ for dep_artifact_name in artifact.get_dependency_artifact_names():
+ dependency = ArtifactElement.new_from_artifact_name(dep_artifact_name, context, task)
+ element._add_build_dependency(dependency)
+
+ return element
+
+ # clear_artifact_name_cache()
#
# Clear the internal artifact refs cache
#
@@ -96,53 +121,24 @@ class ArtifactElement(Element):
# to save memory.
#
@classmethod
- def _clear_artifact_refs_cache(cls):
+ def clear_artifact_name_cache(cls):
cls.__instantiated_artifacts = {}
- # Override Element.get_artifact_name()
- def get_artifact_name(self, key=None):
- return self._ref
-
- # Dummy configure method
+ ########################################################
+ # Implement Element abstract methods #
+ ########################################################
def configure(self, node):
pass
- # Dummy preflight method
def preflight(self):
pass
- # get_dependency_artifact_names()
- #
- # Retrieve the artifact names of all of the dependencies in _Scope.BUILD
- #
- # Returns:
- # (list [str]): A list of artifact refs
- #
- def get_dependency_artifact_names(self):
- artifact = self._get_artifact()
- return artifact.get_dependency_artifact_names()
-
- # configure_sandbox()
- #
- # Configure a sandbox for installing artifacts into
- #
- # Args:
- # sandbox (Sandbox)
- #
def configure_sandbox(self, sandbox):
install_root = self.get_variable("install-root")
# Tell the sandbox to mount the build root and install root
sandbox.mark_directory(install_root)
- # Override Element._calculate_cache_key
- def _calculate_cache_key(self, dependencies=None):
- return self._key
-
- # Override Element._get_cache_key()
- def _get_cache_key(self, strength=None):
- return self._key
-
# verify_artifact_ref()
#