source.py: Split up staging functions into separate codepaths.
Currently we pass a file path string or Directory object to these methods
depending on whether BST_STAGE_VIRTUAL_DIRECTORY is set, which is not very
pretty for plugin developers especially if they are using type annotations
and need to handle `Union[str, Directory]` in these methods.
Instead, created Source.stage_directory() and Source.init_workspace_directory()
to handle the Directory variants of these methods separately.
Also updated `local` and `workspace` plugins to use the new methods.
diff --git a/src/buildstream/plugins/sources/local.py b/src/buildstream/plugins/sources/local.py
index 944324d..54e7679 100644
--- a/src/buildstream/plugins/sources/local.py
+++ b/src/buildstream/plugins/sources/local.py
@@ -90,7 +90,7 @@
# Nothing to do here for a local source
pass # pragma: nocover
- def stage(self, directory):
+ def stage_directory(self, directory):
#
# We've already prepared the CAS while resolving the cache key which
# will happen before staging.
@@ -102,7 +102,7 @@
with self._cache_directory(digest=self.__digest) as cached_directory:
directory.import_files(cached_directory)
- def init_workspace(self, directory):
+ def init_workspace_directory(self, directory):
#
# FIXME: We should be able to stage the workspace from the content
# cached in CAS instead of reimporting from the filesystem
diff --git a/src/buildstream/plugins/sources/workspace.py b/src/buildstream/plugins/sources/workspace.py
index 97a3a08..9127b7c 100644
--- a/src/buildstream/plugins/sources/workspace.py
+++ b/src/buildstream/plugins/sources/workspace.py
@@ -92,13 +92,13 @@
# init_workspace()
#
# Raises AssertionError: existing workspaces should not be reinitialized
- def init_workspace(self, directory: str) -> None:
+ def init_workspace_directory(self, directory: Directory) -> None:
raise AssertionError("Attempting to re-open an existing workspace")
def fetch(self, *, previous_sources_dir=None) -> None: # pylint: disable=arguments-differ
pass # pragma: nocover
- def stage(self, directory):
+ def stage_directory(self, directory):
#
# We've already prepared the CAS while resolving the cache key which
# will happen before staging.
diff --git a/src/buildstream/source.py b/src/buildstream/source.py
index b89aa1a..483c62e 100644
--- a/src/buildstream/source.py
+++ b/src/buildstream/source.py
@@ -78,16 +78,16 @@
Fetch the actual payload for the currently set ref
-* :func:`Source.stage() <buildstream.source.Source.stage>`
+* :func:`Source.stage() <buildstream.source.Source.stage>` / :func:`Source.stage_directory() <buildstream.source.Source.stage_directory>`
Stage the sources for a given ref at a specified location
-* :func:`Source.init_workspace() <buildstream.source.Source.init_workspace>`
+* :func:`Source.init_workspace() <buildstream.source.Source.init_workspace>` / :func:`Source.init_workspace_workspace() <buildstream.source.Source.init_workspace_directory>`
- Stage sources in a local directory for use as a workspace.
+ Stage sources for use as a workspace.
- **Optional**: If left unimplemented, this will default to calling
- :func:`Source.stage() <buildstream.source.Source.stage>`
+ **Optional**: If left unimplemented, these will default to calling
+ :func:`Source.stage() <buildstream.source.Source.stage>` / :func:`Source.stage_directory() <buildstream.source.Source.stage_directory>`
* :func:`Source.get_source_fetchers() <buildstream.source.Source.get_source_fetchers>`
@@ -163,7 +163,7 @@
from . import _yaml, utils
from .node import MappingNode
from .plugin import Plugin
-from .types import SourceRef, Union, CoreWarnings
+from .types import SourceRef, CoreWarnings
from ._exceptions import BstError, ImplError, PluginError
from .exceptions import ErrorDomain
from ._loader.metasource import MetaSource
@@ -307,8 +307,10 @@
BST_STAGE_VIRTUAL_DIRECTORY = False
"""Whether we can stage this source directly to a virtual directory
- When set to true, virtual directories can be passed to the source to stage
- to.
+ When set to True, :func:`Source.stage_directory() <buildstream.source.Source.stage_directory>`
+ and :func:`Source.init_workspace_directory() <buildstream.source.Source.init_workspace_directory>`
+ will be called in place of :func:`Source.stage() <buildstream.source.Source.stage>` and
+ :func:`Source.init_workspace() <buildstream.source.Source.init_workspace>` respectively.
"""
def __init__(
@@ -485,7 +487,7 @@
"""
raise ImplError("Source plugin '{}' does not implement fetch()".format(self.get_kind()))
- def stage(self, directory: Union[str, Directory]) -> None:
+ def stage(self, directory: str) -> None:
"""Stage the sources to a directory
Args:
@@ -502,11 +504,34 @@
"""
raise ImplError("Source plugin '{}' does not implement stage()".format(self.get_kind()))
- def init_workspace(self, directory: str) -> None:
- """Initialises a new workspace
+ def stage_directory(self, directory: Directory) -> None:
+ """Stage the sources to a directory
Args:
- directory: Path of the workspace to init
+ directory: :class:`.Directory` object to stage the source into
+
+ Raises:
+ :class:`.SourceError`
+
+ Implementors should assume that *directory* represents an existing
+ directory root into which the source content can be populated.
+
+ Implementors should raise :class:`.SourceError` when encountering
+ some system error.
+
+ .. note::
+
+ This will be called *instead* of :func:`Source.stage() <buildstream.source.Source.stage>`
+ in the case that :attr:`~buildstream.source.Source.BST_STAGE_VIRTUAL_DIRECTORY` is set
+ for this plugin.
+ """
+ raise ImplError("Source plugin '{}' does not implement stage_directory()".format(self.get_kind()))
+
+ def init_workspace(self, directory: str) -> None:
+ """Stage sources for use as a workspace.
+
+ Args:
+ directory: Path of the workspace to initialize.
Raises:
:class:`.SourceError`
@@ -522,6 +547,32 @@
"""
self.stage(directory)
+ def init_workspace_directory(self, directory: Directory) -> None:
+ """Stage sources for use as a workspace.
+
+ Args:
+ directory: :class:`.Directory` object of the workspace to initialize.
+
+ Raises:
+ :class:`.SourceError`
+
+ Default implementation is to call
+ :func:`Source.stage_directory() <buildstream.source.Source.stage_directory>`.
+
+ Implementors overriding this method should assume that *directory*
+ already exists.
+
+ Implementors should raise :class:`.SourceError` when encountering
+ some system error.
+
+ .. note::
+
+ This will be called *instead* of
+ :func:`Source.init_workspace() <buildstream.source.Source.init_workspace>` in the case that
+ :attr:`~buildstream.source.Source.BST_STAGE_VIRTUAL_DIRECTORY` is set for this plugin.
+ """
+ self.stage_directory(directory)
+
def get_source_fetchers(self) -> Iterable[SourceFetcher]:
"""Get the objects that are used for fetching
@@ -823,7 +874,10 @@
#
def _stage(self, directory):
self.validate_cache()
- self.stage(directory)
+ if isinstance(directory, Directory):
+ self.stage_directory(directory)
+ else:
+ self.stage(directory)
# Wrapper for init_workspace()
def _init_workspace(self, directory):
@@ -831,7 +885,10 @@
directory = FileBasedDirectory(external_directory=directory)
self.validate_cache()
- self.init_workspace(directory)
+ if isinstance(directory, Directory):
+ self.init_workspace_directory(directory)
+ else:
+ self.init_workspace(directory)
# _get_unique_key():
#