// Copyright 2023 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_SERVE_API_REMOTE_SERVE_API_HPP #define INCLUDED_SRC_BUILDTOOL_SERVE_API_REMOTE_SERVE_API_HPP #ifdef BOOTSTRAP_BUILD_TOOL class ServeApi final {}; #else #include #include #include #include #include #include #include #include #include "gsl/gsl" #include "src/buildtool/common/artifact_digest.hpp" #include "src/buildtool/common/remote/remote_common.hpp" #include "src/buildtool/crypto/hash_function.hpp" #include "src/buildtool/execution_api/common/api_bundle.hpp" #include "src/buildtool/execution_api/local/context.hpp" #include "src/buildtool/execution_api/remote/context.hpp" #include "src/buildtool/file_system/git_types.hpp" #include "src/buildtool/file_system/symlinks/pragma_special.hpp" #include "src/buildtool/serve_api/remote/config.hpp" #include "src/buildtool/serve_api/remote/configuration_client.hpp" #include "src/buildtool/serve_api/remote/source_tree_client.hpp" #include "src/buildtool/serve_api/remote/target_client.hpp" #include "src/buildtool/storage/config.hpp" #include "src/buildtool/storage/target_cache_key.hpp" #include "src/utils/cpp/expected.hpp" class ServeApi final { public: explicit ServeApi(ServerAddress const& address, gsl::not_null const& local_context, gsl::not_null const& remote_context, gsl::not_null const& apis) noexcept : stc_{address, local_context->storage_config->hash_function, remote_context}, tc_{address, local_context->storage, remote_context, apis}, cc_{address, remote_context}, storage_config_{*local_context->storage_config}, apis_{*apis} {} ~ServeApi() noexcept = default; ServeApi(ServeApi const&) = delete; ServeApi(ServeApi&&) = delete; auto operator=(ServeApi const&) -> ServeApi& = delete; auto operator=(ServeApi&&) -> ServeApi& = delete; [[nodiscard]] static auto Create( RemoteServeConfig const& serve_config, gsl::not_null const& local_context, gsl::not_null const& remote_context, gsl::not_null const& apis) noexcept -> std::optional { if (serve_config.remote_address) { return std::make_optional(*serve_config.remote_address, local_context, remote_context, apis); } return std::nullopt; } [[nodiscard]] auto RetrieveTreeFromCommit( std::string const& commit, std::string const& subdir = ".", bool sync_tree = false) const noexcept -> SourceTreeClient::result_t { return stc_.ServeCommitTree(commit, subdir, sync_tree); } [[nodiscard]] auto RetrieveTreeFromArchive( std::string const& content, std::string const& archive_type = "archive", std::string const& subdir = ".", std::optional const& resolve_symlinks = std::nullopt, bool sync_tree = false) const noexcept -> SourceTreeClient::result_t { return stc_.ServeArchiveTree( content, archive_type, subdir, resolve_symlinks, sync_tree); } [[nodiscard]] auto RetrieveTreeFromDistdir( std::shared_ptr> const& distfiles, bool sync_tree = false) const noexcept -> SourceTreeClient::result_t { return stc_.ServeDistdirTree(distfiles, sync_tree); } [[nodiscard]] auto RetrieveTreeFromForeignFile( const std::string& content, const std::string& name, bool executable) const noexcept -> SourceTreeClient::result_t { return stc_.ServeForeignFileTree(content, name, executable); } [[nodiscard]] auto ContentInRemoteCAS(std::string const& content) const noexcept -> expected { return stc_.ServeContent(content); } [[nodiscard]] auto TreeInRemoteCAS(std::string const& tree_id) const noexcept -> expected { return stc_.ServeTree(tree_id); } [[nodiscard]] auto CheckRootTree(std::string const& tree_id) const noexcept -> std::optional { return stc_.CheckRootTree(tree_id); } [[nodiscard]] auto GetTreeFromRemote( ArtifactDigest const& digest) const noexcept -> bool { return stc_.GetRemoteTree(digest); } [[nodiscard]] auto ComputeTreeStructure(ArtifactDigest const& digest) const noexcept -> expected { return stc_.ComputeTreeStructure(digest); } [[nodiscard]] auto ServeTargetVariables(std::string const& target_root_id, std::string const& target_file, std::string const& target) const noexcept -> std::optional> { return tc_.ServeTargetVariables(target_root_id, target_file, target); } [[nodiscard]] auto ServeTargetDescription(std::string const& target_root_id, std::string const& target_file, std::string const& target) const noexcept -> std::optional { return tc_.ServeTargetDescription(target_root_id, target_file, target); } [[nodiscard]] auto ServeTarget(const TargetCacheKey& key, const ArtifactDigest& repo_key, bool keep_artifact_root = false) const noexcept -> std::optional { return tc_.ServeTarget(key, repo_key, keep_artifact_root); } [[nodiscard]] auto CheckServeRemoteExecution() const noexcept -> bool { return cc_.CheckServeRemoteExecution(); } [[nodiscard]] auto IsCompatible() const noexcept -> std::optional { 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; /// \brief Download a git tree from serve. /// \param tree Tree to download. /// \return std::monostate if after the call the requested tree can be found /// in the native CAS to which this serve instance is bound to, or an /// unexpected error message on failure. [[nodiscard]] auto DownloadTree(ArtifactDigest const& tree) const noexcept -> expected; private: // source tree service client SourceTreeClient const stc_; // target service client TargetClient const tc_; // configuration service client ConfigurationClient const cc_; StorageConfig const& storage_config_; 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