diff options
Diffstat (limited to 'src/buildtool/computed_roots/lookup_cache.cpp')
-rw-r--r-- | src/buildtool/computed_roots/lookup_cache.cpp | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/src/buildtool/computed_roots/lookup_cache.cpp b/src/buildtool/computed_roots/lookup_cache.cpp new file mode 100644 index 00000000..9021463c --- /dev/null +++ b/src/buildtool/computed_roots/lookup_cache.cpp @@ -0,0 +1,138 @@ +// Copyright 2024 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/computed_roots/lookup_cache.hpp" + +#include <functional> +#include <memory> +#include <vector> + +#include "fmt/core.h" +#include "nlohmann/json.hpp" +#include "src/buildtool/build_engine/base_maps/entity_name_data.hpp" +#include "src/buildtool/build_engine/base_maps/field_reader.hpp" +#include "src/buildtool/build_engine/base_maps/module_name.hpp" +#include "src/buildtool/build_engine/base_maps/targets_file_map.hpp" +#include "src/buildtool/build_engine/expression/configuration.hpp" +#include "src/buildtool/build_engine/expression/target_result.hpp" +#include "src/buildtool/computed_roots/artifacts_root.hpp" +#include "src/buildtool/file_system/file_root.hpp" +#include "src/buildtool/multithreading/task_system.hpp" +#include "src/buildtool/storage/target_cache_entry.hpp" +#include "src/buildtool/storage/target_cache_key.hpp" + +auto LookupCache(BuildMaps::Target::ConfiguredTarget const& ctarget, + gsl::not_null<RepositoryConfig*> const& repository_config, + Storage const& storage, + AsyncMapConsumerLoggerPtr const& logger) + -> expected<std::optional<std::string>, std::monostate> { + auto const* target_root = + repository_config->TargetRoot(ctarget.target.ToModule().repository); + if ((target_root == nullptr) or target_root->IsAbsent()) { + // TODO(aehlig): avoid local installing in case of absent target root of + // the base repository + return expected<std::optional<std::string>, std::monostate>( + std::nullopt); + } + auto repo_key = repository_config->RepositoryKey( + storage, ctarget.target.GetNamedTarget().repository); + if (not repo_key) { + (*logger)(fmt::format("Repository {} is not content-fixed", + nlohmann::json( + ctarget.target.GetNamedTarget().repository)), + /*fatal=*/true); + return unexpected(std::monostate{}); + } + auto targets_file_map = + BuildMaps::Base::CreateTargetsFileMap(repository_config, 1); + nlohmann::json targets_file{}; + bool failed{false}; + { + TaskSystem ts{1}; + targets_file_map.ConsumeAfterKeysReady( + &ts, + {ctarget.target.ToModule()}, + [&targets_file](auto values) { targets_file = *values[0]; }, + [&logger, &failed](auto const& msg, bool fatal) { + (*logger)( + fmt::format("While searching for target description:\n{}", + msg), + fatal); + failed = failed or fatal; + }); + } + if (failed) { + return unexpected(std::monostate{}); + } + auto desc_it = targets_file.find(ctarget.target.GetNamedTarget().name); + if (desc_it == targets_file.end()) { + (*logger)("Not referring to a defined target", /*fatal=*/true); + return unexpected(std::monostate{}); + } + nlohmann::json const& desc = *desc_it; + auto rule_it = desc.find("type"); + if (rule_it == desc.end()) { + (*logger)(fmt::format("No type specified in target-description {}", + desc.dump()), + true); + return unexpected(std::monostate{}); + } + auto const& rule = *rule_it; + if (not(rule.is_string() and rule.get<std::string>() == "export")) { + (*logger)(fmt::format("Target not an export target, but of type {}", + rule.dump()), + true); + return unexpected(std::monostate{}); + } + auto reader = BuildMaps::Base::FieldReader::CreatePtr( + desc, ctarget.target, "export target", logger); + auto flexible_vars = reader->ReadStringList("flexible_config"); + if (not flexible_vars) { + return unexpected(std::monostate{}); + } + auto effective_config = ctarget.config.Prune(*flexible_vars); + auto cache_key = storage.TargetCache().ComputeKey( + *repo_key, ctarget.target.GetNamedTarget(), effective_config); + if (not cache_key) { + (*logger)("Target-cache key generation failed", true); + return unexpected(std::monostate{}); + } + auto target_cache_value = storage.TargetCache().Read(*cache_key); + if (not target_cache_value) { + return expected<std::optional<std::string>, std::monostate>( + std::nullopt); + } + auto const& [entry, info] = *target_cache_value; + auto result = entry.ToResult(); + if (not result) { + (*logger)(fmt::format("Failed to deserialize cache entry {} for key {}", + info.ToString(), + cache_key->Id().ToString()), + true); + return unexpected(std::monostate{}); + } + + auto wrapped_logger = std::make_shared<AsyncMapConsumerLogger>( + [&logger](auto const& msg, bool fatal) { + (*logger)( + fmt::format("While computing git tree for artifacts stage:\n{}", + msg), + fatal); + }); + auto root = ArtifactsRoot(result->artifact_stage, wrapped_logger); + if (not root) { + return unexpected(std::monostate{}); + } + return root; +} |