diff options
Diffstat (limited to 'src/buildtool/execution_api/common/tree_reader_utils.cpp')
-rw-r--r-- | src/buildtool/execution_api/common/tree_reader_utils.cpp | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/src/buildtool/execution_api/common/tree_reader_utils.cpp b/src/buildtool/execution_api/common/tree_reader_utils.cpp new file mode 100644 index 00000000..1ec7edc0 --- /dev/null +++ b/src/buildtool/execution_api/common/tree_reader_utils.cpp @@ -0,0 +1,143 @@ +// 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. + +#include "src/buildtool/execution_api/common/tree_reader_utils.hpp" + +#include <exception> +#include <type_traits> + +#include "nlohmann/json.hpp" +#include "src/buildtool/common/artifact_digest.hpp" +#include "src/buildtool/file_system/object_type.hpp" +#include "src/buildtool/logging/log_level.hpp" +#include "src/buildtool/logging/logger.hpp" +#include "src/utils/cpp/hex_string.hpp" + +namespace { +[[nodiscard]] auto CreateObjectInfo(bazel_re::DirectoryNode const& node) + -> Artifact::ObjectInfo { + return Artifact::ObjectInfo{.digest = ArtifactDigest{node.digest()}, + .type = ObjectType::Tree}; +} + +[[nodiscard]] auto CreateObjectInfo(bazel_re::FileNode const& node) + -> Artifact::ObjectInfo { + return Artifact::ObjectInfo{.digest = ArtifactDigest{node.digest()}, + .type = node.is_executable() + ? ObjectType::Executable + : ObjectType::File}; +} + +[[nodiscard]] auto CreateObjectInfo(bazel_re::SymlinkNode const& node) + -> Artifact::ObjectInfo { + return Artifact::ObjectInfo{ + .digest = ArtifactDigest::Create<ObjectType::File>(node.target()), + .type = ObjectType::Symlink}; +} + +template <typename TTree> +[[nodiscard]] auto TreeToString(TTree const& entries) noexcept + -> std::optional<std::string> { + auto json = nlohmann::json::object(); + TreeReaderUtils::InfoStoreFunc store_infos = + [&json](std::filesystem::path const& path, + Artifact::ObjectInfo const& info) -> bool { + static constexpr bool kSizeUnknown = + std::is_same_v<TTree, GitRepo::tree_entries_t>; + + json[path.string()] = info.ToString(kSizeUnknown); + return true; + }; + + if (TreeReaderUtils::ReadObjectInfos(entries, store_infos)) { + try { + return json.dump(2) + "\n"; + } catch (std::exception const& ex) { + Logger::Log(LogLevel::Error, + "dumping Directory to string failed with:\n{}", + ex.what()); + return std::nullopt; + } + } + Logger::Log(LogLevel::Error, "reading object infos from Directory failed"); + return std::nullopt; +} + +} // namespace + +auto TreeReaderUtils::ReadObjectInfos(bazel_re::Directory const& dir, + InfoStoreFunc const& store_info) noexcept + -> bool { + try { + for (auto const& f : dir.files()) { + if (not store_info(f.name(), CreateObjectInfo(f))) { + return false; + } + } + for (auto const& l : dir.symlinks()) { + if (not store_info(l.name(), CreateObjectInfo(l))) { + return false; + } + } + for (auto const& d : dir.directories()) { + if (not store_info(d.name(), CreateObjectInfo(d))) { + return false; + } + } + } catch (std::exception const& ex) { + Logger::Log(LogLevel::Error, + "reading object infos from Directory failed with:\n{}", + ex.what()); + return false; + } + return true; +} + +auto TreeReaderUtils::ReadObjectInfos(GitRepo::tree_entries_t const& entries, + InfoStoreFunc const& store_info) noexcept + -> bool { + try { + for (auto const& [raw_id, es] : entries) { + auto const hex_id = ToHexString(raw_id); + for (auto const& entry : es) { + if (not store_info( + entry.name, + Artifact::ObjectInfo{ + .digest = ArtifactDigest{hex_id, + /*size is unknown*/ 0, + IsTreeObject(entry.type)}, + .type = entry.type})) { + return false; + } + } + } + } catch (std::exception const& ex) { + Logger::Log(LogLevel::Error, + "reading object infos from Git tree failed with:\n{}", + ex.what()); + return false; + } + return true; +} + +auto TreeReaderUtils::DirectoryToString(bazel_re::Directory const& dir) noexcept + -> std::optional<std::string> { + return TreeToString(dir); +} + +auto TreeReaderUtils::GitTreeToString( + GitRepo::tree_entries_t const& entries) noexcept + -> std::optional<std::string> { + return TreeToString(entries); +} |