diff options
Diffstat (limited to 'src/buildtool/execution_api')
3 files changed, 80 insertions, 0 deletions
diff --git a/src/buildtool/execution_api/bazel_msg/TARGETS b/src/buildtool/execution_api/bazel_msg/TARGETS index d2e7aff2..c036451b 100644 --- a/src/buildtool/execution_api/bazel_msg/TARGETS +++ b/src/buildtool/execution_api/bazel_msg/TARGETS @@ -6,6 +6,7 @@ [ ["src/buildtool/common", "common"] , ["src/buildtool/crypto", "hash_function"] , ["src/buildtool/file_system", "file_system_manager"] + , ["src/buildtool/file_system", "git_cas"] , ["src/utils/cpp", "concepts"] , ["src/utils/cpp", "type_safe_arithmetic"] ] @@ -21,6 +22,7 @@ , ["src/buildtool/common", "common"] , ["src/buildtool/file_system", "file_system_manager"] , ["src/buildtool/execution_engine/dag", "dag"] + , ["src/buildtool/compatibility", "compatibility"] , ["@", "gsl-lite", "", "gsl-lite"] ] , "stage": ["src", "buildtool", "execution_api", "bazel_msg"] diff --git a/src/buildtool/execution_api/bazel_msg/bazel_msg_factory.cpp b/src/buildtool/execution_api/bazel_msg/bazel_msg_factory.cpp index c6b2eb29..7cd9af69 100644 --- a/src/buildtool/execution_api/bazel_msg/bazel_msg_factory.cpp +++ b/src/buildtool/execution_api/bazel_msg/bazel_msg_factory.cpp @@ -12,6 +12,7 @@ #include "gsl-lite/gsl-lite.hpp" #include "src/buildtool/common/bazel_types.hpp" +#include "src/buildtool/compatibility/native_support.hpp" #include "src/buildtool/file_system/file_system_manager.hpp" namespace { @@ -544,6 +545,67 @@ auto BazelMsgFactory::CreateDirectoryDigestFromLocalTree( return std::nullopt; } +auto BazelMsgFactory::CreateGitTreeDigestFromLocalTree( + std::filesystem::path const& root, + FileStoreFunc const& store_file, + TreeStoreFunc const& store_tree) noexcept + -> std::optional<bazel_re::Digest> { + GitCAS::tree_entries_t entries{}; + auto dir_reader = [&entries, &root, &store_file, &store_tree](auto name, + auto type) { + if (IsTreeObject(type)) { + // create and store sub directory + if (auto digest = CreateGitTreeDigestFromLocalTree( + root / name, store_file, store_tree)) { + if (auto raw_id = FromHexString( + NativeSupport::Unprefix(digest->hash()))) { + entries[std::move(*raw_id)].emplace_back(name.string(), + ObjectType::Tree); + return true; + } + } + return false; + } + + // create and store file + try { + const auto full_name = root / name; + const bool is_executable = + FileSystemManager::IsExecutable(full_name, true); + if (auto digest = store_file(full_name, is_executable)) { + if (auto raw_id = FromHexString( + NativeSupport::Unprefix(digest->hash()))) { + entries[std::move(*raw_id)].emplace_back( + name.string(), + is_executable ? ObjectType::Executable + : ObjectType::File); + return true; + } + } + } catch (std::exception const& ex) { + Logger::Log( + LogLevel::Error, "storing file failed with:\n{}", ex.what()); + } + return false; + }; + + if (FileSystemManager::ReadDirectory(root, dir_reader)) { + if (auto tree = GitCAS::CreateShallowTree(entries)) { + try { + if (auto digest = store_tree(tree->second, entries)) { + return *digest; + } + } catch (std::exception const& ex) { + Logger::Log(LogLevel::Error, + "storing tree failed with:\n{}", + ex.what()); + } + return std::nullopt; + } + } + return std::nullopt; +} + auto BazelMsgFactory::CreateActionDigestFromCommandLine( std::vector<std::string> const& cmdline, bazel_re::Digest const& exec_dir, diff --git a/src/buildtool/execution_api/bazel_msg/bazel_msg_factory.hpp b/src/buildtool/execution_api/bazel_msg/bazel_msg_factory.hpp index d850e6c6..8675cc92 100644 --- a/src/buildtool/execution_api/bazel_msg/bazel_msg_factory.hpp +++ b/src/buildtool/execution_api/bazel_msg/bazel_msg_factory.hpp @@ -15,6 +15,7 @@ #include "src/buildtool/execution_api/bazel_msg/bazel_blob.hpp" #include "src/buildtool/execution_api/bazel_msg/bazel_common.hpp" #include "src/buildtool/execution_engine/dag/dag.hpp" +#include "src/buildtool/file_system/git_cas.hpp" /// \brief Factory for creating Bazel API protobuf messages. /// Responsible for creating protobuf messages necessary for Bazel API server @@ -29,6 +30,9 @@ class BazelMsgFactory { using DirStoreFunc = std::function<std::optional<bazel_re::Digest>( std::string const&, bazel_re::Directory const&)>; + using TreeStoreFunc = std::function<std::optional<bazel_re::Digest>( + std::string const&, + GitCAS::tree_entries_t const&)>; /// \brief Read object infos from directory. /// \returns true on success. @@ -60,6 +64,18 @@ class BazelMsgFactory { DirStoreFunc const& store_dir) noexcept -> std::optional<bazel_re::Digest>; + /// \brief Create Git tree digest from local file root. + /// Recursively traverse entire root and store files and directories. + /// \param root Path to local file root. + /// \param store_file Function for storing local file via path. + /// \param store_tree Function for storing git trees. + /// \returns Digest representing the entire file root. + [[nodiscard]] static auto CreateGitTreeDigestFromLocalTree( + std::filesystem::path const& root, + FileStoreFunc const& store_file, + TreeStoreFunc const& store_tree) noexcept + -> std::optional<bazel_re::Digest>; + /// \brief Creates Action digest from command line. /// As part of the internal process, it creates an ActionBundle and /// CommandBundle that can be captured via BlobStoreFunc. |