diff options
author | Raoul Hidalgo Charman <raoul.hidalgocharman@codethink.co.uk> | 2019-05-01 13:38:35 +0100 |
---|---|---|
committer | Raoul Hidalgo Charman <raoul.hidalgocharman@codethink.co.uk> | 2019-05-22 14:09:23 +0100 |
commit | c3f96e1bc32f1728619b144e1d0120349411df66 (patch) | |
tree | c9ce1b8f1d148ba59c0a236482f6d2f255f0b174 /src/buildstream/source.py | |
parent | f958936442b74e46140717a2956b99fc0b835c87 (diff) | |
download | buildstream-c3f96e1bc32f1728619b144e1d0120349411df66.tar.gz |
Add BST_STAGE_VIRTUAL_DIRECTORY option
Add flag to indicate whether sources can stage directly to a virtual
directory. Adds `__stage_previous_sources` method which stages previous
sources taking into account whether they use virtual directories or not.
Part of #983
Diffstat (limited to 'src/buildstream/source.py')
-rw-r--r-- | src/buildstream/source.py | 74 |
1 files changed, 58 insertions, 16 deletions
diff --git a/src/buildstream/source.py b/src/buildstream/source.py index fe94a15d7..f6cefb386 100644 --- a/src/buildstream/source.py +++ b/src/buildstream/source.py @@ -172,6 +172,8 @@ from ._exceptions import BstError, ImplError, ErrorDomain from ._loader.metasource import MetaSource from ._projectrefs import ProjectRefStorage from ._cachekey import generate_key +from .storage import FileBasedDirectory +from .storage.directory import Directory, VirtualDirectoryError class SourceError(BstError): @@ -297,6 +299,15 @@ class Source(Plugin): *Since: 1.4* """ + 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. + + *Since: 1.4* + """ + def __init__(self, context, project, meta, *, alias_override=None, unique_id=None): provenance = _yaml.node_get_provenance(meta.config) super().__init__("{}-{}".format(meta.element_name, meta.element_index), @@ -711,9 +722,7 @@ class Source(Plugin): if self.BST_REQUIRES_PREVIOUS_SOURCES_FETCH: self.__ensure_previous_sources(previous_sources) - with self.tempdir() as staging_directory: - for src in previous_sources: - src._stage(staging_directory) + with self.__stage_previous_sources(previous_sources) as staging_directory: self.__do_fetch(previous_sources_dir=self.__ensure_directory(staging_directory)) else: self.__do_fetch() @@ -727,12 +736,15 @@ class Source(Plugin): # 'directory' option # def _stage(self, directory): - staging_directory = self.__ensure_directory(directory) + directory = self.__ensure_directory(directory) - self.stage(staging_directory) + self.stage(directory) # Wrapper for init_workspace() def _init_workspace(self, directory): + if self.BST_STAGE_VIRTUAL_DIRECTORY: + directory = FileBasedDirectory(external_directory=directory) + directory = self.__ensure_directory(directory) self.init_workspace(directory) @@ -994,9 +1006,8 @@ class Source(Plugin): def _track(self, previous_sources): if self.BST_REQUIRES_PREVIOUS_SOURCES_TRACK: self.__ensure_previous_sources(previous_sources) - with self.tempdir() as staging_directory: - for src in previous_sources: - src._stage(staging_directory) + with self.__stage_previous_sources(previous_sources) \ + as staging_directory: new_ref = self.__do_track(previous_sources_dir=self.__ensure_directory(staging_directory)) else: new_ref = self.__do_track() @@ -1115,6 +1126,24 @@ class Source(Plugin): return clone + # Context manager that stages sources in a cas based or temporary file + # based directory + @contextmanager + def __stage_previous_sources(self, sources): + with self.tempdir() as tempdir: + directory = FileBasedDirectory(external_directory=tempdir) + + for src in sources: + if src.BST_STAGE_VIRTUAL_DIRECTORY: + src._stage(directory) + else: + src._stage(tempdir) + + if self.BST_STAGE_VIRTUAL_DIRECTORY: + yield directory + else: + yield tempdir + # Tries to call fetch for every mirror, stopping once it succeeds def __do_fetch(self, **kwargs): project = self._get_project() @@ -1220,15 +1249,28 @@ class Source(Plugin): # Ensures a fully constructed path and returns it def __ensure_directory(self, directory): - if self.__directory is not None: - directory = os.path.join(directory, self.__directory.lstrip(os.sep)) + if not isinstance(directory, Directory): + if self.__directory is not None: + directory = os.path.join(directory, self.__directory.lstrip(os.sep)) + + try: + os.makedirs(directory, exist_ok=True) + except OSError as e: + raise SourceError("Failed to create staging directory: {}" + .format(e), + reason="ensure-stage-dir-fail") from e + + else: + if self.__directory is not None: + try: + directory = directory.descend( + *self.__directory.lstrip(os.sep).split(os.sep), + create=True) + except VirtualDirectoryError as e: + raise SourceError("Failed to descend into staging directory: {}" + .format(e), + reason="ensure-stage-dir-fail") from e - try: - os.makedirs(directory, exist_ok=True) - except OSError as e: - raise SourceError("Failed to create staging directory: {}" - .format(e), - reason="ensure-stage-dir-fail") from e return directory @classmethod |