diff options
author | Paul Cristian Sarbu <paul.cristian.sarbu@huawei.com> | 2023-12-11 12:25:55 +0100 |
---|---|---|
committer | Paul Cristian Sarbu <paul.cristian.sarbu@huawei.com> | 2023-12-12 14:37:18 +0100 |
commit | 93b92ef2669bed7345eadabbf71ee30c4b7929af (patch) | |
tree | 3da25625b7a3335e88f4bf94e2080ee28ce84d36 /src | |
parent | e6123964c4470426a444d190ed5b1c58a74b7731 (diff) | |
download | justbuild-93b92ef2669bed7345eadabbf71ee30c4b7929af.tar.gz |
serve target: Move server-side helper methods in own library
Diffstat (limited to 'src')
-rw-r--r-- | src/buildtool/serve_api/serve_service/TARGETS | 33 | ||||
-rw-r--r-- | src/buildtool/serve_api/serve_service/target.cpp | 262 | ||||
-rw-r--r-- | src/buildtool/serve_api/serve_service/target.hpp | 34 | ||||
-rw-r--r-- | src/buildtool/serve_api/serve_service/target_utils.cpp | 283 | ||||
-rw-r--r-- | src/buildtool/serve_api/serve_service/target_utils.hpp | 61 |
5 files changed, 376 insertions, 297 deletions
diff --git a/src/buildtool/serve_api/serve_service/TARGETS b/src/buildtool/serve_api/serve_service/TARGETS index d169ae4b..0f921dee 100644 --- a/src/buildtool/serve_api/serve_service/TARGETS +++ b/src/buildtool/serve_api/serve_service/TARGETS @@ -72,22 +72,22 @@ , "deps": [ ["src/buildtool/logging", "logging"] , ["@", "gsl", "", "gsl"] - , ["src/buildtool/common", "config"] + , ["src/buildtool/common/remote", "remote_common"] , ["src/buildtool/execution_api/remote", "config"] , ["src/buildtool/execution_api/common", "create_execution_api"] + , ["src/buildtool/execution_api/common", "common"] ] , "stage": ["src", "buildtool", "serve_api", "serve_service"] , "private-deps": [ ["@", "fmt", "", "fmt"] , ["@", "json", "", "json"] + , "target_utils" , ["src/buildtool/build_engine/base_maps", "entity_name"] , ["src/buildtool/build_engine/base_maps", "entity_name_data"] , ["src/buildtool/build_engine/expression", "expression"] , ["src/buildtool/build_engine/expression", "expression_ptr_interface"] , ["src/buildtool/build_engine/target_map", "configured_target"] - , ["src/buildtool/build_engine/target_map", "target_map"] - , ["src/buildtool/file_system", "git_cas"] - , ["src/buildtool/file_system", "git_repo"] + , ["src/buildtool/build_engine/target_map", "result_map"] , ["src/buildtool/graph_traverser", "graph_traverser"] , ["src/buildtool/main", "analyse"] , ["src/buildtool/main", "build_utils"] @@ -110,4 +110,29 @@ , "stage": ["src", "buildtool", "serve_api", "serve_service"] , "private-deps": [["src/buildtool/execution_api/remote", "config"]] } +, "target_utils": + { "type": ["@", "rules", "CC", "library"] + , "name": ["target_utils"] + , "hdrs": ["target_utils.hpp"] + , "srcs": ["target_utils.cpp"] + , "deps": + [ ["@", "gsl", "", "gsl"] + , ["src/buildtool/common/remote", "remote_common"] + , ["src/buildtool/common", "config"] + , ["src/buildtool/logging", "logging"] + ] + , "stage": ["src", "buildtool", "serve_api", "serve_service"] + , "private-deps": + [ ["@", "fmt", "", "fmt"] + , ["@", "json", "", "json"] + , ["src/buildtool/file_system", "file_root"] + , ["src/buildtool/file_system", "git_cas"] + , ["src/buildtool/file_system", "git_repo"] + , ["src/buildtool/file_system", "object_type"] + , ["src/buildtool/logging", "log_level"] + , ["src/buildtool/serve_api/remote", "config"] + , ["src/buildtool/storage", "config"] + , ["src/buildtool/storage", "storage"] + ] + } } diff --git a/src/buildtool/serve_api/serve_service/target.cpp b/src/buildtool/serve_api/serve_service/target.cpp index 12ca64ad..b4a0968a 100644 --- a/src/buildtool/serve_api/serve_service/target.cpp +++ b/src/buildtool/serve_api/serve_service/target.cpp @@ -14,12 +14,7 @@ #include "src/buildtool/serve_api/serve_service/target.hpp" -#include <filesystem> -#include <string> -#include <utility> - #include "fmt/core.h" -#include "fmt/format.h" #include "nlohmann/json.hpp" #include "src/buildtool/build_engine/base_maps/entity_name.hpp" #include "src/buildtool/build_engine/base_maps/entity_name_data.hpp" @@ -30,8 +25,6 @@ #include "src/buildtool/build_engine/target_map/result_map.hpp" #include "src/buildtool/common/artifact.hpp" #include "src/buildtool/common/artifact_digest.hpp" -#include "src/buildtool/file_system/git_cas.hpp" -#include "src/buildtool/file_system/git_repo.hpp" #include "src/buildtool/file_system/object_type.hpp" #include "src/buildtool/graph_traverser/graph_traverser.hpp" #include "src/buildtool/main/analyse.hpp" @@ -39,210 +32,12 @@ #include "src/buildtool/multithreading/task_system.hpp" #include "src/buildtool/progress_reporting/progress_reporter.hpp" #include "src/buildtool/serve_api/remote/config.hpp" +#include "src/buildtool/serve_api/serve_service/target_utils.hpp" #include "src/buildtool/storage/config.hpp" #include "src/buildtool/storage/storage.hpp" #include "src/buildtool/storage/target_cache_key.hpp" #include "src/utils/cpp/verify_hash.hpp" -auto TargetService::IsTreeInRepo(std::string const& tree_id, - std::filesystem::path const& repo_path, - std::shared_ptr<Logger> const& logger) - -> bool { - if (auto git_cas = GitCAS::Open(repo_path)) { - if (auto repo = GitRepo::Open(git_cas)) { - // wrap logger for GitRepo call - auto wrapped_logger = std::make_shared<GitRepo::anon_logger_t>( - [logger, repo_path, tree_id](auto const& msg, bool fatal) { - if (fatal) { - auto err = fmt::format( - "ServeTarget: While checking existence of tree {} " - "in repository {}:\n{}", - tree_id, - repo_path.string(), - msg); - logger->Emit(LogLevel::Info, err); - } - }); - if (auto res = repo->CheckTreeExists(tree_id, wrapped_logger)) { - return *res; - } - } - } - return false; // tree not found -} - -auto TargetService::GetServingRepository(std::string const& tree_id, - std::shared_ptr<Logger> const& logger) - -> std::optional<std::filesystem::path> { - // try the Git cache repository - if (IsTreeInRepo(tree_id, StorageConfig::GitRoot(), logger)) { - return StorageConfig::GitRoot(); - } - // check the known repositories - for (auto const& path : RemoteServeConfig::KnownRepositories()) { - if (IsTreeInRepo(tree_id, path, logger)) { - return path; - } - } - return std::nullopt; // tree cannot be served -} - -auto TargetService::DetermineRoots( - std::string const& main_repo, - std::filesystem::path const& repo_config_path, - gsl::not_null<RepositoryConfig*> const& repository_config, - std::shared_ptr<Logger> const& logger) -> std::optional<std::string> { - // parse repository configuration file - auto repos = nlohmann::json::object(); - try { - std::ifstream fs(repo_config_path); - repos = nlohmann::json::parse(fs); - if (not repos.is_object()) { - return fmt::format( - "Repository configuration file {} does not contain a map.", - repo_config_path.string()); - } - } catch (std::exception const& ex) { - return fmt::format("Parsing repository config file {} failed with:\n{}", - repo_config_path.string(), - ex.what()); - } - if (not repos.contains(main_repo)) { - return fmt::format( - "Repository configuration does not contain expected main " - "repository {}", - main_repo); - } - // populate RepositoryConfig instance - std::string error_msg; - for (auto const& [repo, desc] : repos.items()) { - // root parser - auto parse_keyword_root = - [&desc = desc, &repo = repo, &error_msg = error_msg, logger]( - std::string const& keyword) -> std::optional<FileRoot> { - auto it = desc.find(keyword); - if (it != desc.end()) { - if (auto parsed_root = - FileRoot::ParseRoot(repo, keyword, *it, &error_msg)) { - // check that root has absent-like format - if (not parsed_root->first.IsAbsent()) { - error_msg = fmt::format( - "Expected {} to have absent Git tree format, but " - "found {}", - keyword, - it->dump()); - return std::nullopt; - } - // find the serving repository for the root tree - auto tree_id = *parsed_root->first.GetAbsentTreeId(); - auto repo_path = GetServingRepository(tree_id, logger); - if (not repo_path) { - error_msg = fmt::format( - "{} tree {} is not known", keyword, tree_id); - return std::nullopt; - } - // set the root as present - if (auto root = FileRoot::FromGit( - *repo_path, - tree_id, - parsed_root->first.IgnoreSpecial())) { - return root; - } - } - error_msg = - fmt::format("Failed to parse {} {}", keyword, it->dump()); - return std::nullopt; - } - error_msg = - fmt::format("Missing {} for repository {}", keyword, repo); - return std::nullopt; - }; - - std::optional<FileRoot> ws_root = parse_keyword_root("workspace_root"); - if (not ws_root) { - return error_msg; - } - auto info = RepositoryConfig::RepositoryInfo{std::move(*ws_root)}; - - if (auto target_root = parse_keyword_root("target_root")) { - info.target_root = std::move(*target_root); - } - else { - return error_msg; - } - - if (auto rule_root = parse_keyword_root("rule_root")) { - info.rule_root = std::move(*rule_root); - } - else { - return error_msg; - } - - if (auto expression_root = parse_keyword_root("expression_root")) { - info.expression_root = std::move(*expression_root); - } - else { - return error_msg; - } - - auto it_bindings = desc.find("bindings"); - if (it_bindings != desc.end()) { - if (not it_bindings->is_object()) { - return fmt::format( - "bindings has to be a string-string map, but found {}", - it_bindings->dump()); - } - for (auto const& [local_name, global_name] : it_bindings->items()) { - if (not repos.contains(global_name)) { - return fmt::format( - "Binding {} for {} in {} does not refer to a " - "defined repository.", - global_name, - local_name, - repo); - } - info.name_mapping[local_name] = global_name; - } - } - else { - return fmt::format("Missing bindings for repository {}", repo); - } - - auto parse_keyword_file_name = - [&desc = desc, &repo = repo, &error_msg = error_msg]( - std::string* keyword_file_name, - std::string const& keyword) -> bool { - auto it = desc.find(keyword); - if (it != desc.end()) { - *keyword_file_name = *it; - return true; - } - error_msg = - fmt::format("Missing {} for repository {}", keyword, repo); - return false; - }; - - if (not parse_keyword_file_name(&info.target_file_name, - "target_file_name")) { - return error_msg; - } - - if (not parse_keyword_file_name(&info.rule_file_name, - "rule_file_name")) { - return error_msg; - } - - if (not parse_keyword_file_name(&info.expression_file_name, - "expression_file_name")) { - return error_msg; - } - - repository_config->SetInfo(repo, std::move(info)); - } - // success - return std::nullopt; -} - auto TargetService::ServeTarget( ::grpc::ServerContext* /*context*/, const ::justbuild::just_serve::ServeTargetRequest* request, @@ -577,61 +372,6 @@ auto TargetService::ServeTarget( return ::grpc::Status{::grpc::StatusCode::INTERNAL, msg}; } -auto TargetService::GetBlobContent(std::filesystem::path const& repo_path, - std::string const& tree_id, - std::string const& rel_path, - std::shared_ptr<Logger> const& logger) - -> std::optional<std::pair<bool, std::optional<std::string>>> { - if (auto git_cas = GitCAS::Open(repo_path)) { - if (auto repo = GitRepo::Open(git_cas)) { - // check if tree exists - auto wrapped_logger = std::make_shared<GitRepo::anon_logger_t>( - [logger, repo_path, tree_id](auto const& msg, bool fatal) { - if (fatal) { - auto err = fmt::format( - "ServeTargetVariables: While checking if tree {} " - "exists in repository {}:\n{}", - tree_id, - repo_path.string(), - msg); - logger->Emit(LogLevel::Debug, err); - } - }); - if (repo->CheckTreeExists(tree_id, wrapped_logger) == true) { - // get tree entry by path - if (auto entry_info = - repo->GetObjectByPathFromTree(tree_id, rel_path)) { - wrapped_logger = std::make_shared<GitRepo::anon_logger_t>( - [logger, repo_path, blob_id = entry_info->id]( - auto const& msg, bool fatal) { - if (fatal) { - auto err = fmt::format( - "ServeTargetVariables: While retrieving " - "blob {} from repository {}:\n{}", - blob_id, - repo_path.string(), - msg); - logger->Emit(LogLevel::Debug, err); - } - }); - // get blob content - return repo->TryReadBlob(entry_info->id, wrapped_logger); - } - // trace failure to get entry - auto err = fmt::format( - "ServeTargetVariables: Failed to retrieve entry {} in " - "tree {} from repository {}", - rel_path, - tree_id, - repo_path.string()); - logger->Emit(LogLevel::Debug, err); - return std::pair(false, std::nullopt); // could not read blob - } - } - } - return std::nullopt; // tree not found or errors while retrieving tree -} - auto TargetService::ServeTargetVariables( ::grpc::ServerContext* /*context*/, const ::justbuild::just_serve::ServeTargetVariablesRequest* request, diff --git a/src/buildtool/serve_api/serve_service/target.hpp b/src/buildtool/serve_api/serve_service/target.hpp index 5cb18426..b8257152 100644 --- a/src/buildtool/serve_api/serve_service/target.hpp +++ b/src/buildtool/serve_api/serve_service/target.hpp @@ -18,12 +18,13 @@ #include <filesystem> #include <memory> #include <optional> +#include <string> #include "gsl/gsl" #include "justbuild/just_serve/just_serve.grpc.pb.h" #include "src/buildtool/common/remote/remote_common.hpp" -#include "src/buildtool/common/repository_config.hpp" #include "src/buildtool/execution_api/common/create_execution_api.hpp" +#include "src/buildtool/execution_api/common/execution_api.hpp" #include "src/buildtool/execution_api/remote/config.hpp" #include "src/buildtool/logging/logger.hpp" @@ -77,37 +78,6 @@ class TargetService final : public justbuild::just_serve::Target::Service { // used for storing and retrieving target-level cache entries gsl::not_null<IExecutionApi::Ptr> const local_api_{ CreateExecutionApi(std::nullopt)}; - - /// \brief Check if tree exists in the given repository. - [[nodiscard]] static auto IsTreeInRepo( - std::string const& tree_id, - std::filesystem::path const& repo_path, - std::shared_ptr<Logger> const& logger) -> bool; - - /// \brief For a given tree id, find the known repository that can serve it. - [[nodiscard]] static auto GetServingRepository( - std::string const& tree_id, - std::shared_ptr<Logger> const& logger) - -> std::optional<std::filesystem::path>; - - /// \brief Parse the stored repository configuration blob and populate the - /// RepositoryConfig instance. - /// \returns nullopt on success, error message as a string otherwise. - [[nodiscard]] static auto DetermineRoots( - std::string const& main_repo, - std::filesystem::path const& repo_config_path, - gsl::not_null<RepositoryConfig*> const& repository_config, - std::shared_ptr<Logger> const& logger) -> std::optional<std::string>; - - /// \brief Get the blob content at given path inside a Git tree. - /// \returns If tree found, pair of "no-internal-errors" flag and content of - /// blob at the path specified if blob exists, nullopt otherwise. - [[nodiscard]] static auto GetBlobContent( - std::filesystem::path const& repo_path, - std::string const& tree_id, - std::string const& rel_path, - std::shared_ptr<Logger> const& logger) - -> std::optional<std::pair<bool, std::optional<std::string>>>; }; #endif // INCLUDED_SRC_BUILD_SERVE_API_SERVE_SERVICE_TARGET_HPP diff --git a/src/buildtool/serve_api/serve_service/target_utils.cpp b/src/buildtool/serve_api/serve_service/target_utils.cpp new file mode 100644 index 00000000..c9268f63 --- /dev/null +++ b/src/buildtool/serve_api/serve_service/target_utils.cpp @@ -0,0 +1,283 @@ +// 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. + +#include "src/buildtool/serve_api/serve_service/target_utils.hpp" + +#include <exception> +#include <fstream> +#include <string> + +#include "fmt/core.h" +#include "nlohmann/json.hpp" +#include "src/buildtool/file_system/file_root.hpp" +#include "src/buildtool/file_system/git_cas.hpp" +#include "src/buildtool/file_system/git_repo.hpp" +#include "src/buildtool/file_system/object_type.hpp" +#include "src/buildtool/logging/log_level.hpp" +#include "src/buildtool/serve_api/remote/config.hpp" +#include "src/buildtool/storage/config.hpp" +#include "src/buildtool/storage/storage.hpp" + +auto IsTreeInRepo(std::string const& tree_id, + std::filesystem::path const& repo_path, + std::shared_ptr<Logger> const& logger) -> bool { + if (auto git_cas = GitCAS::Open(repo_path)) { + if (auto repo = GitRepo::Open(git_cas)) { + // wrap logger for GitRepo call + auto wrapped_logger = std::make_shared<GitRepo::anon_logger_t>( + [logger, repo_path, tree_id](auto const& msg, bool fatal) { + if (fatal) { + auto err = fmt::format( + "ServeTarget: While checking existence of tree {} " + "in repository {}:\n{}", + tree_id, + repo_path.string(), + msg); + logger->Emit(LogLevel::Info, err); + } + }); + if (auto res = repo->CheckTreeExists(tree_id, wrapped_logger)) { + return *res; + } + } + } + return false; // tree not found +} + +auto GetServingRepository(std::string const& tree_id, + std::shared_ptr<Logger> const& logger) + -> std::optional<std::filesystem::path> { + // try the Git cache repository + if (IsTreeInRepo(tree_id, StorageConfig::GitRoot(), logger)) { + return StorageConfig::GitRoot(); + } + // check the known repositories + for (auto const& path : RemoteServeConfig::KnownRepositories()) { + if (IsTreeInRepo(tree_id, path, logger)) { + return path; + } + } + return std::nullopt; // tree cannot be served +} + +auto DetermineRoots(std::string const& main_repo, + std::filesystem::path const& repo_config_path, + gsl::not_null<RepositoryConfig*> const& repository_config, + std::shared_ptr<Logger> const& logger) + -> std::optional<std::string> { + // parse repository configuration file + auto repos = nlohmann::json::object(); + try { + std::ifstream fs(repo_config_path); + repos = nlohmann::json::parse(fs); + if (not repos.is_object()) { + return fmt::format( + "Repository configuration file {} does not contain a map.", + repo_config_path.string()); + } + } catch (std::exception const& ex) { + return fmt::format("Parsing repository config file {} failed with:\n{}", + repo_config_path.string(), + ex.what()); + } + if (not repos.contains(main_repo)) { + return fmt::format( + "Repository configuration does not contain expected main " + "repository {}", + main_repo); + } + // populate RepositoryConfig instance + std::string error_msg; + for (auto const& [repo, desc] : repos.items()) { + // root parser + auto parse_keyword_root = + [&desc = desc, &repo = repo, &error_msg = error_msg, logger]( + std::string const& keyword) -> std::optional<FileRoot> { + auto it = desc.find(keyword); + if (it != desc.end()) { + if (auto parsed_root = + FileRoot::ParseRoot(repo, keyword, *it, &error_msg)) { + // check that root has absent-like format + if (not parsed_root->first.IsAbsent()) { + error_msg = fmt::format( + "Expected {} to have absent Git tree format, but " + "found {}", + keyword, + it->dump()); + return std::nullopt; + } + // find the serving repository for the root tree + auto tree_id = *parsed_root->first.GetAbsentTreeId(); + auto repo_path = GetServingRepository(tree_id, logger); + if (not repo_path) { + error_msg = fmt::format( + "{} tree {} is not known", keyword, tree_id); + return std::nullopt; + } + // set the root as present + if (auto root = FileRoot::FromGit( + *repo_path, + tree_id, + parsed_root->first.IgnoreSpecial())) { + return root; + } + } + error_msg = + fmt::format("Failed to parse {} {}", keyword, it->dump()); + return std::nullopt; + } + error_msg = + fmt::format("Missing {} for repository {}", keyword, repo); + return std::nullopt; + }; + + std::optional<FileRoot> ws_root = parse_keyword_root("workspace_root"); + if (not ws_root) { + return error_msg; + } + auto info = RepositoryConfig::RepositoryInfo{std::move(*ws_root)}; + + if (auto target_root = parse_keyword_root("target_root")) { + info.target_root = std::move(*target_root); + } + else { + return error_msg; + } + + if (auto rule_root = parse_keyword_root("rule_root")) { + info.rule_root = std::move(*rule_root); + } + else { + return error_msg; + } + + if (auto expression_root = parse_keyword_root("expression_root")) { + info.expression_root = std::move(*expression_root); + } + else { + return error_msg; + } + + auto it_bindings = desc.find("bindings"); + if (it_bindings != desc.end()) { + if (not it_bindings->is_object()) { + return fmt::format( + "bindings has to be a string-string map, but found {}", + it_bindings->dump()); + } + for (auto const& [local_name, global_name] : it_bindings->items()) { + if (not repos.contains(global_name)) { + return fmt::format( + "Binding {} for {} in {} does not refer to a " + "defined repository.", + global_name, + local_name, + repo); + } + info.name_mapping[local_name] = global_name; + } + } + else { + return fmt::format("Missing bindings for repository {}", repo); + } + + auto parse_keyword_file_name = + [&desc = desc, &repo = repo, &error_msg = error_msg]( + std::string* keyword_file_name, + std::string const& keyword) -> bool { + auto it = desc.find(keyword); + if (it != desc.end()) { + *keyword_file_name = *it; + return true; + } + error_msg = + fmt::format("Missing {} for repository {}", keyword, repo); + return false; + }; + + if (not parse_keyword_file_name(&info.target_file_name, + "target_file_name")) { + return error_msg; + } + + if (not parse_keyword_file_name(&info.rule_file_name, + "rule_file_name")) { + return error_msg; + } + + if (not parse_keyword_file_name(&info.expression_file_name, + "expression_file_name")) { + return error_msg; + } + + repository_config->SetInfo(repo, std::move(info)); + } + // success + return std::nullopt; +} + +auto GetBlobContent(std::filesystem::path const& repo_path, + std::string const& tree_id, + std::string const& rel_path, + std::shared_ptr<Logger> const& logger) + -> std::optional<std::pair<bool, std::optional<std::string>>> { + if (auto git_cas = GitCAS::Open(repo_path)) { + if (auto repo = GitRepo::Open(git_cas)) { + // check if tree exists + auto wrapped_logger = std::make_shared<GitRepo::anon_logger_t>( + [logger, repo_path, tree_id](auto const& msg, bool fatal) { + if (fatal) { + auto err = fmt::format( + "ServeTargetVariables: While checking if tree {} " + "exists in repository {}:\n{}", + tree_id, + repo_path.string(), + msg); + logger->Emit(LogLevel::Debug, err); + } + }); + if (repo->CheckTreeExists(tree_id, wrapped_logger) == true) { + // get tree entry by path + if (auto entry_info = + repo->GetObjectByPathFromTree(tree_id, rel_path)) { + wrapped_logger = std::make_shared<GitRepo::anon_logger_t>( + [logger, repo_path, blob_id = entry_info->id]( + auto const& msg, bool fatal) { + if (fatal) { + auto err = fmt::format( + "ServeTargetVariables: While retrieving " + "blob {} from repository {}:\n{}", + blob_id, + repo_path.string(), + msg); + logger->Emit(LogLevel::Debug, err); + } + }); + // get blob content + return repo->TryReadBlob(entry_info->id, wrapped_logger); + } + // trace failure to get entry + auto err = fmt::format( + "ServeTargetVariables: Failed to retrieve entry {} in " + "tree {} from repository {}", + rel_path, + tree_id, + repo_path.string()); + logger->Emit(LogLevel::Debug, err); + return std::pair(false, std::nullopt); // could not read blob + } + } + } + return std::nullopt; // tree not found or errors while retrieving tree +} diff --git a/src/buildtool/serve_api/serve_service/target_utils.hpp b/src/buildtool/serve_api/serve_service/target_utils.hpp new file mode 100644 index 00000000..ee94ff38 --- /dev/null +++ b/src/buildtool/serve_api/serve_service/target_utils.hpp @@ -0,0 +1,61 @@ +// 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_BUILD_SERVE_API_SERVE_SERVICE_TARGET_UTILS_HPP +#define INCLUDED_SRC_BUILD_SERVE_API_SERVE_SERVICE_TARGET_UTILS_HPP + +#include <filesystem> +#include <memory> +#include <optional> +#include <string> +#include <utility> + +#include "gsl/gsl" +#include "src/buildtool/common/remote/remote_common.hpp" +#include "src/buildtool/common/repository_config.hpp" +#include "src/buildtool/logging/logger.hpp" + +// Methods used by ServeTarget remote service + +/// \brief Check if tree exists in the given repository. +[[nodiscard]] auto IsTreeInRepo(std::string const& tree_id, + std::filesystem::path const& repo_path, + std::shared_ptr<Logger> const& logger) -> bool; + +/// \brief For a given tree id, find the known repository that can serve it. +[[nodiscard]] auto GetServingRepository(std::string const& tree_id, + std::shared_ptr<Logger> const& logger) + -> std::optional<std::filesystem::path>; + +/// \brief Parse the stored repository configuration blob and populate the +/// RepositoryConfig instance. +/// \returns nullopt on success, error message as a string otherwise. +[[nodiscard]] auto DetermineRoots( + std::string const& main_repo, + std::filesystem::path const& repo_config_path, + gsl::not_null<RepositoryConfig*> const& repository_config, + std::shared_ptr<Logger> const& logger) -> std::optional<std::string>; + +// Methods used by ServeTargetVariables remote service + +/// \brief Get the blob content at given path inside a Git tree. +/// \returns If tree found, pair of "no-internal-errors" flag and content of +/// blob at the path specified if blob exists, nullopt otherwise. +[[nodiscard]] auto GetBlobContent(std::filesystem::path const& repo_path, + std::string const& tree_id, + std::string const& rel_path, + std::shared_ptr<Logger> const& logger) + -> std::optional<std::pair<bool, std::optional<std::string>>>; + +#endif // INCLUDED_SRC_BUILD_SERVE_API_SERVE_SERVICE_TARGET_UTILS_HPP |