diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/buildtool/serve_api/remote/TARGETS | 11 | ||||
-rw-r--r-- | src/buildtool/serve_api/remote/serve_api.cpp | 111 | ||||
-rw-r--r-- | src/buildtool/serve_api/remote/serve_api.hpp | 36 |
3 files changed, 158 insertions, 0 deletions
diff --git a/src/buildtool/serve_api/remote/TARGETS b/src/buildtool/serve_api/remote/TARGETS index 2e587eaa..102109ed 100644 --- a/src/buildtool/serve_api/remote/TARGETS +++ b/src/buildtool/serve_api/remote/TARGETS @@ -40,6 +40,7 @@ { "type": ["@", "rules", "CC", "library"] , "name": ["serve_api"] , "hdrs": ["serve_api.hpp"] + , "srcs": ["serve_api.cpp"] , "deps": [ "config" , "configuration_client" @@ -57,6 +58,16 @@ , ["src/buildtool/storage", "storage"] , ["src/utils/cpp", "expected"] ] + , "private-deps": + [ ["@", "fmt", "", "fmt"] + , ["src/buildtool/common", "config"] + , ["src/buildtool/common", "protocol_traits"] + , ["src/buildtool/crypto", "hash_function"] + , ["src/buildtool/execution_api/common", "common"] + , ["src/buildtool/execution_api/serve", "mr_git_api"] + , ["src/buildtool/execution_api/utils", "rehash_utils"] + , ["src/buildtool/file_system", "object_type"] + ] , "stage": ["src", "buildtool", "serve_api", "remote"] } , "target_client": diff --git a/src/buildtool/serve_api/remote/serve_api.cpp b/src/buildtool/serve_api/remote/serve_api.cpp new file mode 100644 index 00000000..37911e1d --- /dev/null +++ b/src/buildtool/serve_api/remote/serve_api.cpp @@ -0,0 +1,111 @@ +// Copyright 2025 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 BOOTSTRAP_BUILD_TOOL + +#include "src/buildtool/serve_api/remote/serve_api.hpp" + +#include "fmt/core.h" +#include "src/buildtool/common/artifact.hpp" +#include "src/buildtool/common/protocol_traits.hpp" +#include "src/buildtool/common/repository_config.hpp" +#include "src/buildtool/crypto/hash_function.hpp" +#include "src/buildtool/execution_api/common/execution_api.hpp" +#include "src/buildtool/execution_api/serve/mr_git_api.hpp" +#include "src/buildtool/execution_api/utils/rehash_utils.hpp" +#include "src/buildtool/file_system/object_type.hpp" + +auto ServeApi::UploadTree(ArtifactDigest const& tree, + std::filesystem::path const& git_repo) const noexcept + -> expected<std::monostate, UploadError> { + static constexpr bool kIsSyncError = true; + if (not tree.IsTree() or not ProtocolTraits::IsNative(tree.GetHashType())) { + return unexpected{UploadError{ + fmt::format("Not a git tree: {}", tree.hash()), not kIsSyncError}}; + } + + RepositoryConfig repo; + if (not repo.SetGitCAS(git_repo)) { + return unexpected{UploadError{ + fmt::format("Failed to SetGitCAS at {}", git_repo.string()), + not kIsSyncError}}; + } + + bool const with_rehashing = + not ProtocolTraits::IsNative(storage_config_.hash_function.GetType()); + + // Create a native storage config if rehashing is needed: + std::optional<StorageConfig> native_storage_config; + if (with_rehashing) { + auto config = StorageConfig::Builder::Rebuild(storage_config_) + .SetHashType(HashFunction::Type::GitSHA1) + .Build(); + if (not config.has_value()) { + return unexpected{ + UploadError{fmt::format("Failed to create native storage: {}", + std::move(config).error()), + not kIsSyncError}}; + } + native_storage_config.emplace(*config); + } + + std::shared_ptr<IExecutionApi> git_api; + if (with_rehashing) { + git_api = std::make_shared<MRGitApi>( + &repo, &*native_storage_config, &storage_config_, &*apis_.local); + } + else { + git_api = std::make_shared<MRGitApi>(&repo, &storage_config_); + } + + // Upload tree to remote CAS: + if (not git_api->RetrieveToCas( + {Artifact::ObjectInfo{tree, ObjectType::Tree}}, *apis_.remote)) { + return unexpected{ + UploadError{fmt::format("Failed to sync tree {} from repository {}", + tree.hash(), + git_repo.string()), + not kIsSyncError}}; + } + + ArtifactDigest on_remote = tree; + // Read rehashed digest if needed: + if (with_rehashing) { + auto rehashed = RehashUtils::ReadRehashedDigest( + tree, *native_storage_config, storage_config_, /*from_git=*/true); + if (not rehashed.has_value()) { + return unexpected{ + UploadError{std::move(rehashed).error(), not kIsSyncError}}; + } + + if (not rehashed.value().has_value()) { + return unexpected{UploadError{ + fmt::format("No digest provided to sync root tree {}", + tree.hash()), + kIsSyncError}}; + } + on_remote = rehashed.value()->digest; + } + + // Ask serve to get tree from remote: + if (not this->GetTreeFromRemote(on_remote)) { + return unexpected{UploadError{ + fmt::format("Serve endpoint failed to sync root tree {}.", + tree.hash()), + kIsSyncError}}; + } + return std::monostate{}; +} + +#endif diff --git a/src/buildtool/serve_api/remote/serve_api.hpp b/src/buildtool/serve_api/remote/serve_api.hpp index d6f15c3d..975e7a17 100644 --- a/src/buildtool/serve_api/remote/serve_api.hpp +++ b/src/buildtool/serve_api/remote/serve_api.hpp @@ -19,10 +19,13 @@ class ServeApi final {}; #else +#include <filesystem> #include <memory> #include <optional> #include <string> #include <unordered_map> +#include <utility> +#include <variant> #include <vector> #include "gsl/gsl" @@ -161,6 +164,16 @@ class ServeApi final { return cc_.IsCompatible(); } + class UploadError; + /// \brief Upload a git tree from git repo to serve. + /// \param tree Tree to upload. + /// \param git_repo Git repository where the tree can be found. + /// \return std::monostate if the tree is available for this serve + /// instance after the call, or an unexpected UploadError on failure. + [[nodiscard]] auto UploadTree(ArtifactDigest const& tree, + std::filesystem::path const& git_repo) + const noexcept -> expected<std::monostate, UploadError>; + private: // source tree service client SourceTreeClient const stc_; @@ -173,6 +186,29 @@ class ServeApi final { ApiBundle const& apis_; }; +class ServeApi::UploadError final { + public: + [[nodiscard]] auto Message() const& noexcept -> std::string const& { + return message_; + } + + [[nodiscard]] auto Message() && noexcept -> std::string { + return std::move(message_); + } + + [[nodiscard]] auto IsSyncError() const noexcept -> bool { + return is_sync_error_; + } + + private: + friend ServeApi; + explicit UploadError(std::string message, bool is_sync_error) noexcept + : message_{std::move(message)}, is_sync_error_{is_sync_error} {} + + std::string message_; + bool is_sync_error_; +}; + #endif // BOOTSTRAP_BUILD_TOOL #endif // INCLUDED_SRC_BUILDTOOL_SERVE_API_REMOTE_SERVE_API_HPP |