diff options
-rw-r--r-- | buildstream/_frontend/main.py | 9 | ||||
-rw-r--r-- | buildstream/_pipeline.py | 32 | ||||
-rw-r--r-- | buildstream/element.py | 18 |
3 files changed, 57 insertions, 2 deletions
diff --git a/buildstream/_frontend/main.py b/buildstream/_frontend/main.py index 3ac6b5222..91fc750ac 100644 --- a/buildstream/_frontend/main.py +++ b/buildstream/_frontend/main.py @@ -504,16 +504,21 @@ def shell(app, element, sysroot, build, command): help="Overwrite files existing in checkout directory") @click.option('--integrate/--no-integrate', default=True, is_flag=True, help="Whether to run integration commands") +@click.option('--metadata', '-m', default=False, is_flag=True, + help="Check out the artifact's metadata, instead of the contents") @click.argument('element', type=click.Path(dir_okay=False, readable=True)) @click.argument('directory', type=click.Path(file_okay=False)) @click.pass_obj -def checkout(app, element, directory, force, integrate): +def checkout(app, element, directory, force, integrate, metadata): """Checkout a built artifact to the specified directory """ app.initialize([element]) try: - app.pipeline.checkout(directory, force, integrate) + if metadata: + app.pipeline.checkout_metadata(directory, force) + else: + app.pipeline.checkout(directory, force, integrate) click.echo("") except BstError as e: click.echo("") diff --git a/buildstream/_pipeline.py b/buildstream/_pipeline.py index 90ed899ea..aa0299c52 100644 --- a/buildstream/_pipeline.py +++ b/buildstream/_pipeline.py @@ -490,6 +490,38 @@ class Pipeline(): except OSError as e: raise PipelineError("Failed to copy files: {}".format(e)) from e + # checkout_metadata() + # + # Checkout the metadata from the pipeline target artifact to the specified directory + # + # Args: + # directory (str): The directory to checkout the artifact to + # force (bool): Force overwrite files which exist in `directory` + # + def checkout_metadata(self, directory, force): + # We only have one target in a checkout command + target = self.targets[0] + + try: + os.makedirs(directory, exist_ok=True) + except OSError as e: + raise PipelineError("Failed to create metadata checkout directory: {}".format(e)) from e + + if not os.access(directory, os.W_OK): + raise PipelineError("Directory {} not writable".format(directory)) + + if not force and os.listdir(directory): + raise PipelineError("Checkout directory is not empty: {}" + .format(directory)) + + metadata_dirs = target.metadata_dirs() + with target.timed_activity("Copying metadata files to {}".format(directory)): + for metadata_type, metadata_dir in metadata_dirs.items(): + try: + utils.copy_files(metadata_dir, os.path.join(directory, metadata_type)) + except OSError as e: + raise PipelineError("Failed to copy files: {}".format(e)) from e + # open_workspace # # Open a project workspace. diff --git a/buildstream/element.py b/buildstream/element.py index 86dd2b8dc..d2976cfe2 100644 --- a/buildstream/element.py +++ b/buildstream/element.py @@ -543,6 +543,24 @@ class Element(Plugin): return None + def metadata_dirs(self): + """Return a map of the paths that contain the artifact's metadata. + + The paths will point inside the artifact cache and must be treated + as read-only. + + Returns: + (dict): A dictionary mapping each type of metadata to the + location where it is stored. + """ + + self._assert_cached() + artifact_base = self.__artifacts.extract(self) + return { + 'logs': os.path.join(artifact_base, 'logs'), + 'meta': os.path.join(artifact_base, 'meta'), + } + ############################################################# # Abstract Element Methods # ############################################################# |