summaryrefslogtreecommitdiff
path: root/src/buildtool/execution_api/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/buildtool/execution_api/common')
-rw-r--r--src/buildtool/execution_api/common/TARGETS2
-rw-r--r--src/buildtool/execution_api/common/tree_reader.hpp160
2 files changed, 162 insertions, 0 deletions
diff --git a/src/buildtool/execution_api/common/TARGETS b/src/buildtool/execution_api/common/TARGETS
index 210cbb3a..214e87be 100644
--- a/src/buildtool/execution_api/common/TARGETS
+++ b/src/buildtool/execution_api/common/TARGETS
@@ -6,6 +6,7 @@
, "execution_api.hpp"
, "execution_action.hpp"
, "execution_response.hpp"
+ , "tree_reader.hpp"
]
, "srcs": ["execution_api.cpp"]
, "deps":
@@ -20,6 +21,7 @@
, ["src/buildtool/logging", "logging"]
, ["src/utils/cpp", "gsl"]
, ["src/utils/cpp", "hex_string"]
+ , ["src/buildtool/file_system", "git_repo"]
]
, "stage": ["src", "buildtool", "execution_api", "common"]
}
diff --git a/src/buildtool/execution_api/common/tree_reader.hpp b/src/buildtool/execution_api/common/tree_reader.hpp
new file mode 100644
index 00000000..0a6057fe
--- /dev/null
+++ b/src/buildtool/execution_api/common/tree_reader.hpp
@@ -0,0 +1,160 @@
+// Copyright 2024 Huawei Cloud Computing Technology Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef INCLUDED_SRC_BUILDTOOL_EXECUTION_API_COMMON_TREE_READER_HPP
+#define INCLUDED_SRC_BUILDTOOL_EXECUTION_API_COMMON_TREE_READER_HPP
+
+#include <filesystem>
+#include <functional>
+#include <optional>
+#include <utility>
+#include <vector>
+
+#include "src/buildtool/common/artifact.hpp"
+#include "src/buildtool/common/bazel_types.hpp"
+#include "src/buildtool/execution_api/bazel_msg/bazel_msg_factory.hpp"
+#include "src/buildtool/file_system/git_repo.hpp"
+#include "src/buildtool/file_system/object_type.hpp"
+
+struct ReadTreeResult final {
+ std::vector<std::filesystem::path> paths;
+ std::vector<Artifact::ObjectInfo> infos;
+};
+
+template <typename TImpl>
+class TreeReader final {
+ public:
+ template <typename... Args>
+ explicit TreeReader(Args&&... args) noexcept
+ : impl_(std::forward<Args>(args)...) {}
+
+ /// \brief Reads the flat content of a tree and returns object infos of all
+ /// its direct entries (trees and blobs).
+ /// \param tree_digest Digest of the tree.
+ /// \param parent Local parent path.
+ /// \returns A struct containing filesystem paths and object infos.
+ [[nodiscard]] auto ReadDirectTreeEntries(
+ ArtifactDigest const& digest,
+ std::filesystem::path const& parent) const noexcept
+ -> std::optional<ReadTreeResult> {
+ ReadTreeResult result;
+
+ BazelMsgFactory::InfoStoreFunc store_info =
+ [&result, &parent](std::filesystem::path const& path,
+ Artifact::ObjectInfo const& info) {
+ result.paths.emplace_back(parent / path);
+ result.infos.emplace_back(info);
+ return true;
+ };
+
+ if (Compatibility::IsCompatible()) {
+ auto tree = impl_.ReadDirectory(digest);
+ if (tree and not BazelMsgFactory::ReadObjectInfosFromDirectory(
+ *tree, store_info)) {
+ return std::nullopt;
+ }
+ }
+ else {
+ auto tree = impl_.ReadGitTree(digest);
+ if (tree and not BazelMsgFactory::ReadObjectInfosFromGitTree(
+ *tree, store_info)) {
+ return std::nullopt;
+ }
+ }
+ return result;
+ }
+
+ /// \brief Traverses a tree recursively and retrieves object infos of all
+ /// found blobs (leafs). Tree objects are by default not added to the result
+ /// list, but converted to a path name.
+ /// \param tree_digest Digest of the tree.
+ /// \param parent Local parent path.
+ /// \param include_trees Include leaf tree objects (empty trees).
+ /// \returns A struct containing filesystem paths and object infos.
+ [[nodiscard]] auto RecursivelyReadTreeLeafs(
+ ArtifactDigest const& digest,
+ std::filesystem::path const& parent,
+ bool include_trees = false) const noexcept
+ -> std::optional<ReadTreeResult> {
+ ReadTreeResult result;
+
+ auto store = [&result](std::filesystem::path const& path,
+ Artifact::ObjectInfo const& info) {
+ result.paths.emplace_back(path);
+ result.infos.emplace_back(info);
+ return true;
+ };
+
+ try {
+ if (ReadObjectInfosRecursively(
+ store, parent, digest, include_trees)) {
+ return result;
+ }
+ } catch (...) {
+ // fallthrough
+ }
+ return std::nullopt;
+ }
+
+ private:
+ TImpl impl_;
+
+ [[nodiscard]] static inline auto IsDirectoryEmpty(
+ bazel_re::Directory const& dir) noexcept -> bool {
+ return dir.files().empty() and dir.directories().empty() and
+ dir.symlinks().empty();
+ }
+
+ [[nodiscard]] auto ReadObjectInfosRecursively(
+ BazelMsgFactory::InfoStoreFunc const& store,
+ std::filesystem::path const& parent,
+ ArtifactDigest const& digest,
+ bool const include_trees) const -> bool {
+ BazelMsgFactory::InfoStoreFunc internal_store =
+ [this, &store, &parent, include_trees](
+ std::filesystem::path const& path,
+ Artifact::ObjectInfo const& info) -> bool {
+ return IsTreeObject(info.type)
+ ? ReadObjectInfosRecursively(
+ store, parent / path, info.digest, include_trees)
+ : store(parent / path, info);
+ };
+
+ if (Compatibility::IsCompatible()) {
+ if (auto tree = impl_.ReadDirectory(digest)) {
+ if (include_trees and IsDirectoryEmpty(*tree)) {
+ if (not store(parent, {digest, ObjectType::Tree})) {
+ return false;
+ }
+ }
+ return BazelMsgFactory::ReadObjectInfosFromDirectory(
+ *tree, internal_store);
+ }
+ }
+ else {
+ if (auto tree = impl_.ReadGitTree(digest)) {
+ if (include_trees and tree->empty()) {
+ if (not store(parent, {digest, ObjectType::Tree})) {
+ return false;
+ }
+ }
+ return BazelMsgFactory::ReadObjectInfosFromGitTree(
+ *tree, internal_store);
+ }
+ }
+ return false;
+ }
+};
+
+#endif // INCLUDED_SRC_BUILDTOOL_EXECUTION_API_COMMON_TREE_READER_HPP