blob: 08d9251220e7dbb7b7b0b37f2c4e09a1071b0ea9 [file] [log] [blame]
# Copyright 2021 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from recipe_engine import recipe_api
from RECIPE_MODULES.recipe_engine.file.api import SymlinkTree
class ArchiveTree(object):
"""A representation of a tree to archive in RBE-CAS.
This tree uses the same interface as api.file.SymlinkTree.
"""
def __init__(self, root, api):
"""See ArchiveApi.tree for the public constructor."""
self._tree = api.cas_util.hardlink_tree(root)
self._api = api
@property
def root(self):
"""The root (Path) of the tree."""
return self._tree.root
def register_link(self, target, linkname):
"""Registers a pair of paths to link."""
self._tree.register_link(
self._api.path.abs_to_path(self._api.path.realpath(target)),
linkname,
)
def create_links(self, name):
"""Creates all registered links on disk."""
self._tree.create_links(name)
class HardlinkTree(SymlinkTree):
"""A representation of a tree of hardlinks.
This tree differs from the SymlinkTree in the resource passed to it.
See ArchiveApi.hardlink_tree for the public constructor.
"""
pass
class CasUtilApi(recipe_api.RecipeApi):
"""API for archiving and accessing archived files in RBE-CAS."""
def upload(
self,
staging_dir,
upload_paths=(),
step_name=None,
output_property=None,
):
"""Returns the digest of the archived tree created from the provided
staging_dir.
Args:
staging_dir (Path): The root of the directory to upload.
upload_paths (list(UploadPath)): A list of files under the staging_dir
to upload if not uploading the entire directory.
output_property (str): The name of the output property to set with
the digest.
"""
# TODO(fxbug.dev/62939): The two codepaths below mirror what was in
# upload_isolated before the migration happened so that step names stay
# the same. Combine the two paths once we confirm there are no
# dependencies on the step names.
if output_property:
with self.m.step.nest(step_name or "cas") as step:
cas_digest = self.m.cas.archive("archive", staging_dir, *upload_paths)
step.presentation.properties[output_property] = cas_digest
else:
cas_digest = self.m.cas.archive(
step_name or "archive", staging_dir, *upload_paths
)
return cas_digest
def download(self, digest, output_dir, step_name=None):
"""Downloads the archive with the CAS digest into output_dir."""
self.m.cas.download(
step_name or "download", digest=digest, output_dir=output_dir
)
def tree(self, root):
"""Creates an ArchiveTree, given a root directory.
Args:
root (Path): root of a tree to archive.
"""
return ArchiveTree(root, self.m)
def hardlink_tree(self, root):
"""Creates a HardlinkTree, given a root directory.
Args:
root (Path): root of a tree of hardlinks.
"""
# Pass in the file module to include all necessary deps for SymlinkTree
# which HardlinkTree is a child of.
return HardlinkTree(root, self.m.file.m, self.resource("hardlink.py"))