summaryrefslogtreecommitdiff
path: root/src/buildtool/execution_api/bazel_msg
diff options
context:
space:
mode:
Diffstat (limited to 'src/buildtool/execution_api/bazel_msg')
-rw-r--r--src/buildtool/execution_api/bazel_msg/bazel_msg_factory.cpp223
1 files changed, 52 insertions, 171 deletions
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 3c25fa72..48c8b062 100644
--- a/src/buildtool/execution_api/bazel_msg/bazel_msg_factory.cpp
+++ b/src/buildtool/execution_api/bazel_msg/bazel_msg_factory.cpp
@@ -32,138 +32,11 @@
#include "src/utils/cpp/hex_string.hpp"
namespace {
-
-/// \brief Abstract interface for bundle (message, content, and digest).
-/// Provides getters for content, corresponding digest, and creating a blob.
-class IBundle {
- public:
- using Ptr = std::unique_ptr<IBundle>;
- using ContentCreateFunc = std::function<std::optional<std::string>()>;
- using DigestCreateFunc =
- std::function<bazel_re::Digest(std::string const&)>;
-
- IBundle() = default;
- IBundle(IBundle const&) = delete;
- IBundle(IBundle&&) = delete;
- auto operator=(IBundle const&) -> IBundle& = delete;
- auto operator=(IBundle&&) -> IBundle& = delete;
- virtual ~IBundle() noexcept = default;
-
- [[nodiscard]] virtual auto Content() const& noexcept
- -> std::string const& = 0;
- [[nodiscard]] virtual auto Digest() const& noexcept
- -> bazel_re::Digest const& = 0;
- [[nodiscard]] auto MakeBlob(bool is_exec) const noexcept -> BazelBlob {
- return BazelBlob{Digest(), Content(), is_exec};
- }
-};
-
-/// \brief Sparse Bundle implementation for protobuf messages.
-/// It is called "Sparse" as it does not contain its own Digest. Instead, the
-/// protobuf message's Digest is used.
-/// \tparam T The actual protobuf message type.
-template <typename T>
-class SparseBundle final : public IBundle {
- public:
- using Ptr = std::unique_ptr<SparseBundle<T>>;
-
- [[nodiscard]] auto Message() const noexcept -> T const& { return msg_; }
-
- [[nodiscard]] auto Content() const& noexcept -> std::string const& final {
- return content_;
- }
-
- [[nodiscard]] auto Digest() const& noexcept
- -> bazel_re::Digest const& final {
- return msg_.digest();
- }
-
- [[nodiscard]] static auto Create(T const& msg,
- ContentCreateFunc const& content_creator,
- DigestCreateFunc const& digest_creator)
- -> Ptr {
- auto content = content_creator();
- if (content) {
- // create bundle with message and content
- Ptr bundle{new SparseBundle<T>{msg, std::move(*content)}};
-
- // create digest
- bundle->msg_.set_allocated_digest(gsl::owner<bazel_re::Digest*>{
- new bazel_re::Digest{digest_creator(bundle->content_)}});
- return bundle;
- }
- return Ptr{};
- }
-
- SparseBundle(SparseBundle const&) = delete;
- SparseBundle(SparseBundle&&) = delete;
- auto operator=(SparseBundle const&) -> SparseBundle& = delete;
- auto operator=(SparseBundle&&) -> SparseBundle& = delete;
- ~SparseBundle() noexcept final = default;
-
- private:
- T msg_{}; /**< Protobuf message */
- std::string content_{}; /**< Content the message's digest refers to */
-
- explicit SparseBundle(T msg, std::string&& content)
- : msg_{std::move(msg)}, content_{std::move(content)} {}
-};
-
-/// \brief Full Bundle implementation for protobuf messages.
-/// Contains its own Digest memory, as the protobuf message does not contain
-/// one itself.
-/// \tparam T The actual protobuf message type.
-template <typename T>
-class FullBundle final : public IBundle {
- public:
- using Ptr = std::unique_ptr<FullBundle<T>>;
-
- [[nodiscard]] auto Message() const noexcept -> T const& { return msg_; }
-
- auto Content() const& noexcept -> std::string const& final {
- return content_;
- }
-
- auto Digest() const& noexcept -> bazel_re::Digest const& final {
- return digest_;
- }
-
- [[nodiscard]] static auto Create(T const& msg,
- ContentCreateFunc const& content_creator,
- DigestCreateFunc const& digest_creator)
- -> Ptr {
- auto content = content_creator();
- if (content) {
- // create bundle with message and content
- Ptr bundle{new FullBundle<T>{msg, std::move(*content)}};
-
- // create digest
- bundle->digest_ = digest_creator(bundle->content_);
- return bundle;
- }
- return Ptr{};
- }
-
- FullBundle(FullBundle const&) = delete;
- FullBundle(FullBundle&&) = delete;
- auto operator=(FullBundle const&) -> FullBundle& = delete;
- auto operator=(FullBundle&&) -> FullBundle& = delete;
- ~FullBundle() noexcept final = default;
-
- private:
- T msg_{}; /**< Protobuf message */
- bazel_re::Digest digest_{}; /**< Digest of content */
- std::string content_{}; /**< Content the digest refers to */
-
- explicit FullBundle(T msg, std::string&& content)
- : msg_{std::move(msg)}, content_{std::move(content)} {}
+struct DirectoryNodeBundle final {
+ bazel_re::DirectoryNode const message;
+ BazelBlob const bazel_blob;
};
-using DirectoryNodeBundle = SparseBundle<bazel_re::DirectoryNode>;
-using SymlinkNodeBundle = FullBundle<bazel_re::SymlinkNode>;
-using ActionBundle = FullBundle<bazel_re::Action>;
-using CommandBundle = FullBundle<bazel_re::Command>;
-
/// \brief Serialize protobuf message to string.
template <class T>
[[nodiscard]] auto SerializeMessage(T const& message) noexcept
@@ -306,19 +179,27 @@ template <class T>
/// \brief Create bundle for protobuf message DirectoryNode from Directory.
[[nodiscard]] auto CreateDirectoryNodeBundle(std::string const& dir_name,
bazel_re::Directory const& dir)
- -> DirectoryNodeBundle::Ptr {
- // setup protobuf message except digest
+ -> std::optional<DirectoryNodeBundle> {
+ auto content = SerializeMessage(dir);
+ if (not content) {
+ return std::nullopt;
+ }
+ auto digest = ArtifactDigest::Create<ObjectType::File>(*content);
+
auto msg = CreateDirectoryNode(dir_name);
- auto content_creator = [&dir] { return SerializeMessage(dir); };
- auto digest_creator = [](std::string const& content) -> bazel_re::Digest {
- return ArtifactDigest::Create<ObjectType::File>(content);
- };
- return DirectoryNodeBundle::Create(msg, content_creator, digest_creator);
+ msg.set_allocated_digest(
+ gsl::owner<bazel_re::Digest*>{new bazel_re::Digest{digest}});
+
+ return DirectoryNodeBundle{
+ .message = std::move(msg),
+ .bazel_blob = BazelBlob{
+ std::move(digest), std::move(*content), /*is_exec=*/false}};
}
/// \brief Create bundle for protobuf message Command from args strings.
[[nodiscard]] auto CreateCommandBundle(
- BazelMsgFactory::ActionDigestRequest const& request) -> CommandBundle::Ptr {
+ BazelMsgFactory::ActionDigestRequest const& request)
+ -> std::optional<BazelBlob> {
bazel_re::Command msg;
// DEPRECATED as of v2.2: platform properties are now specified
// directly in the action. See documentation note in the
@@ -338,19 +219,19 @@ template <class T>
request.env_vars->end(),
pb::back_inserter(msg.mutable_environment_variables()));
- auto content_creator = [&msg] { return SerializeMessage(msg); };
-
- auto digest_creator = [](std::string const& content) -> bazel_re::Digest {
- return ArtifactDigest::Create<ObjectType::File>(content);
- };
-
- return CommandBundle::Create(msg, content_creator, digest_creator);
+ auto content = SerializeMessage(msg);
+ if (not content) {
+ return std::nullopt;
+ }
+ auto digest = ArtifactDigest::Create<ObjectType::File>(*content);
+ return BazelBlob{digest, std::move(*content), /*is_exec=*/false};
}
/// \brief Create bundle for protobuf message Action from Command.
[[nodiscard]] auto CreateActionBundle(
bazel_re::Digest const& command,
- BazelMsgFactory::ActionDigestRequest const& request) -> ActionBundle::Ptr {
+ BazelMsgFactory::ActionDigestRequest const& request)
+ -> std::optional<BazelBlob> {
using seconds = std::chrono::seconds;
using nanoseconds = std::chrono::nanoseconds;
auto sec = std::chrono::duration_cast<seconds>(request.timeout);
@@ -374,13 +255,12 @@ template <class T>
// (https://github.com/bazelbuild/remote-apis/blob/e1fe21be4c9ae76269a5a63215bb3c72ed9ab3f0/build/bazel/remote/execution/v2/remote_execution.proto#L516)
msg.set_allocated_platform(CreatePlatform(*request.properties).release());
- auto content_creator = [&msg] { return SerializeMessage(msg); };
-
- auto digest_creator = [](std::string const& content) -> bazel_re::Digest {
- return ArtifactDigest::Create<ObjectType::File>(content);
- };
-
- return ActionBundle::Create(msg, content_creator, digest_creator);
+ auto content = SerializeMessage(msg);
+ if (not content) {
+ return std::nullopt;
+ }
+ auto digest = ArtifactDigest::Create<ObjectType::File>(*content);
+ return BazelBlob{digest, std::move(*content), /*is_exec=*/false};
}
/// \brief Convert `DirectoryTree` to `DirectoryNodeBundle`.
@@ -391,7 +271,7 @@ template <class T>
BazelMsgFactory::LinkDigestResolveFunc const& resolve_links,
BazelMsgFactory::BlobProcessFunc const& process_blob,
std::filesystem::path const& parent = "") noexcept
- -> DirectoryNodeBundle::Ptr {
+ -> std::optional<DirectoryNodeBundle> {
std::vector<bazel_re::FileNode> file_nodes{};
std::vector<bazel_re::DirectoryNode> dir_nodes{};
std::vector<std::string> symlink_names{};
@@ -403,19 +283,18 @@ template <class T>
auto const dir_bundle = DirectoryTreeToBundle(
name, dir, resolve_links, process_blob, parent / name);
if (not dir_bundle) {
- return nullptr;
+ return std::nullopt;
}
- dir_nodes.emplace_back(dir_bundle->Message());
- if (not process_blob(dir_bundle->MakeBlob(
- /*is_exec=*/false))) {
- return nullptr;
+ dir_nodes.emplace_back(dir_bundle->message);
+ if (not process_blob(BazelBlob{dir_bundle->bazel_blob})) {
+ return std::nullopt;
}
}
else {
auto const& artifact = std::get<Artifact const*>(node);
auto const& object_info = artifact->Info();
if (not object_info) {
- return nullptr;
+ return std::nullopt;
}
if (IsTreeObject(object_info->type)) {
dir_nodes.emplace_back(
@@ -441,9 +320,9 @@ template <class T>
symlink_names, symlink_digests, resolve_links),
{}));
} catch (...) {
- return nullptr;
+ return std::nullopt;
}
- return nullptr;
+ return std::nullopt;
}
} // namespace
@@ -456,13 +335,13 @@ auto BazelMsgFactory::CreateDirectoryDigestFromTree(
if (auto bundle =
DirectoryTreeToBundle("", tree, resolve_links, process_blob)) {
try {
- if (not process_blob(bundle->MakeBlob(/*is_exec=*/false))) {
+ if (not process_blob(BazelBlob{bundle->bazel_blob})) {
return std::nullopt;
}
} catch (...) {
return std::nullopt;
}
- return bundle->Digest();
+ return bundle->bazel_blob.digest;
}
return std::nullopt;
}
@@ -644,19 +523,21 @@ auto BazelMsgFactory::CreateGitTreeDigestFromLocalTree(
auto BazelMsgFactory::CreateActionDigestFromCommandLine(
ActionDigestRequest const& request) -> std::optional<bazel_re::Digest> {
auto cmd = CreateCommandBundle(request);
- if (cmd == nullptr) {
+ if (not cmd) {
return std::nullopt;
}
- auto action = CreateActionBundle(cmd->Digest(), request);
- if (action == nullptr) {
+ auto action = CreateActionBundle(cmd->digest, request);
+ if (not action) {
return std::nullopt;
}
- if (request.store_blob) {
- (*request.store_blob)(cmd->MakeBlob(/*is_exec=*/false));
- (*request.store_blob)(action->MakeBlob(/*is_exec=*/false));
+ if (not request.store_blob) {
+ return action->digest;
}
- return action->Digest();
+ auto digest = action->digest;
+ std::invoke(*request.store_blob, std::move(*cmd));
+ std::invoke(*request.store_blob, std::move(*action));
+ return digest;
}