diff options
5 files changed, 62 insertions, 32 deletions
diff --git a/src/buildtool/execution_api/common/tree_reader.hpp b/src/buildtool/execution_api/common/tree_reader.hpp index 7ec66163..42bf20e6 100644 --- a/src/buildtool/execution_api/common/tree_reader.hpp +++ b/src/buildtool/execution_api/common/tree_reader.hpp @@ -15,6 +15,7 @@ #ifndef INCLUDED_SRC_BUILDTOOL_EXECUTION_API_COMMON_TREE_READER_HPP #define INCLUDED_SRC_BUILDTOOL_EXECUTION_API_COMMON_TREE_READER_HPP +#include <cstddef> #include <filesystem> #include <optional> #include <utility> @@ -107,6 +108,32 @@ class TreeReader final { } } + /// \brief Traverse a tree recursively and stage all artifacts to paths. + /// \param infos Infos to be staged + /// \param outputs Paths to be used for staging + /// \return True if outputs contain corresponding infos. + [[nodiscard]] auto StageTo(std::vector<Artifact::ObjectInfo> const& infos, + std::vector<std::filesystem::path> const& + outputs) const noexcept -> bool { + if (infos.size() != outputs.size()) { + return false; + } + + for (std::size_t i = 0; i < infos.size(); ++i) { + auto const& info = infos[i]; + if (IsTreeObject(info.type)) { + auto result = RecursivelyReadTreeLeafs(info.digest, outputs[i]); + if (not result or not StageTo(result->infos, result->paths)) { + return false; + } + } + else if (not impl_.StageBlobTo(info, outputs[i])) { + return false; + } + } + return true; + } + private: TImpl impl_; diff --git a/src/buildtool/execution_api/local/local_api.hpp b/src/buildtool/execution_api/local/local_api.hpp index e87c0d23..7e7bee1c 100644 --- a/src/buildtool/execution_api/local/local_api.hpp +++ b/src/buildtool/execution_api/local/local_api.hpp @@ -101,39 +101,13 @@ class LocalApi final : public IExecutionApi { return false; } - for (std::size_t i{}; i < artifacts_info.size(); ++i) { + auto const reader = + TreeReader<LocalCasReader>{&local_context_.storage->CAS()}; + for (std::size_t i = 0; i < artifacts_info.size(); ++i) { auto const& info = artifacts_info[i]; - if (IsTreeObject(info.type)) { - // read object infos from sub tree and call retrieve recursively - auto reader = - TreeReader<LocalCasReader>{&local_context_.storage->CAS()}; - auto const result = reader.RecursivelyReadTreeLeafs( - info.digest, output_paths[i]); - if (not result) { - if (git_api_ and not git_api_->RetrieveToPaths( - {info}, {output_paths[i]})) { - return false; - } - } - else if (not RetrieveToPaths(result->infos, result->paths)) { - return false; - } - } - else { - auto const blob_path = local_context_.storage->CAS().BlobPath( - info.digest, IsExecutableObject(info.type)); - if (not blob_path) { - if (git_api_ and not git_api_->RetrieveToPaths( - {info}, {output_paths[i]})) { - return false; - } - } - else if (not FileSystemManager::CreateDirectory( - output_paths[i].parent_path()) or - not FileSystemManager::CopyFileAs< - /*kSetEpochTime=*/true, - /*kSetWritable=*/true>( - *blob_path, output_paths[i], info.type)) { + if (not reader.StageTo({info}, {output_paths[i]})) { + if (not git_api_ or + not git_api_->RetrieveToPaths({info}, {output_paths[i]})) { Logger::Log(LogLevel::Error, "staging to output path {} failed.", output_paths[i].string()); diff --git a/src/buildtool/execution_api/local/local_cas_reader.cpp b/src/buildtool/execution_api/local/local_cas_reader.cpp index 5365404f..c88f5c15 100644 --- a/src/buildtool/execution_api/local/local_cas_reader.cpp +++ b/src/buildtool/execution_api/local/local_cas_reader.cpp @@ -145,6 +145,23 @@ auto LocalCasReader::DumpBlob(Artifact::ObjectInfo const& info, return path ? DumpRaw(*path, dumper) : false; } +auto LocalCasReader::StageBlobTo( + Artifact::ObjectInfo const& info, + std::filesystem::path const& output) const noexcept -> bool { + if (not IsBlobObject(info.type)) { + return false; + } + auto const blob_path = + cas_.BlobPath(info.digest, IsExecutableObject(info.type)); + if (not blob_path) { + return false; + } + return FileSystemManager::CreateDirectory(output.parent_path()) and + FileSystemManager::CopyFileAs</*kSetEpochTime=*/true, + /*kSetWritable=*/true>( + *blob_path, output, info.type); +} + auto LocalCasReader::DumpRaw(std::filesystem::path const& path, DumpCallback const& dumper) noexcept -> bool { auto closer = [](gsl::owner<FILE*> file) -> void { diff --git a/src/buildtool/execution_api/local/local_cas_reader.hpp b/src/buildtool/execution_api/local/local_cas_reader.hpp index 8fe9afd4..090aa9d1 100644 --- a/src/buildtool/execution_api/local/local_cas_reader.hpp +++ b/src/buildtool/execution_api/local/local_cas_reader.hpp @@ -52,6 +52,10 @@ class LocalCasReader final { DumpCallback const& dumper) const noexcept -> bool; + [[nodiscard]] auto StageBlobTo( + Artifact::ObjectInfo const& info, + std::filesystem::path const& output) const noexcept -> bool; + [[nodiscard]] auto IsNativeProtocol() const noexcept -> bool; private: diff --git a/src/buildtool/execution_api/remote/bazel/bazel_network_reader.hpp b/src/buildtool/execution_api/remote/bazel/bazel_network_reader.hpp index d5b537f1..0bfa9a84 100644 --- a/src/buildtool/execution_api/remote/bazel/bazel_network_reader.hpp +++ b/src/buildtool/execution_api/remote/bazel/bazel_network_reader.hpp @@ -16,6 +16,7 @@ #define INCLUDED_SRC_BUILDTOOL_EXECUTION_API_REMOTE_BAZEL_BAZEL_TREE_READER_HPP #include <cstddef> +#include <filesystem> #include <functional> #include <iterator> #include <optional> @@ -64,6 +65,13 @@ class BazelNetworkReader final { DumpCallback const& dumper) const noexcept -> bool; + // NOLINTNEXTLINE(readability-convert-member-functions-to-static) + [[nodiscard]] auto StageBlobTo( + Artifact::ObjectInfo const& /*info*/, + std::filesystem::path const& /*output*/) const noexcept -> bool { + return false; // not implemented + } + [[nodiscard]] auto IsNativeProtocol() const noexcept -> bool; [[nodiscard]] auto ReadSingleBlob(bazel_re::Digest const& digest) |