// Copyright 2022 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_COMMON_REPOSITORY_CONFIG_HPP #define INCLUDED_SRC_BUILDTOOL_COMMON_REPOSITORY_CONFIG_HPP #include #include #include #include #include #include #include #include // std::move #include "gsl/gsl" #include "nlohmann/json.hpp" #include "src/buildtool/common/artifact_digest.hpp" #include "src/buildtool/crypto/hash_function.hpp" #include "src/buildtool/file_system/file_root.hpp" #include "src/buildtool/file_system/git_cas.hpp" #include "src/buildtool/file_system/git_tree.hpp" #include "src/buildtool/file_system/precomputed_root.hpp" #include "src/buildtool/logging/log_level.hpp" #include "src/buildtool/multithreading/atomic_value.hpp" #include "src/buildtool/storage/config.hpp" #include "src/buildtool/storage/storage.hpp" class RepositoryConfig { public: struct RepositoryInfo { // NOLINT(bugprone-exception-escape) FileRoot workspace_root; FileRoot target_root{workspace_root}; FileRoot rule_root{target_root}; FileRoot expression_root{rule_root}; std::map name_mapping{}; std::string target_file_name{"TARGETS"}; std::string rule_file_name{"RULES"}; std::string expression_file_name{"EXPRESSIONS"}; // Return base content description without bindings if all roots are // content fixed or return std::nullopt otherwise. [[nodiscard]] auto BaseContentDescription() const -> std::optional; }; void SetInfo(std::string const& repo, RepositoryInfo&& info) { repos_[repo].base_desc = info.BaseContentDescription(); repos_[repo].info = std::move(info); repos_[repo].key.Reset(); duplicates_.Reset(); } [[nodiscard]] auto SetGitCAS( std::filesystem::path const& repo_path, gsl::not_null const& storage_config, LogLevel log_level = LogLevel::Warning) noexcept -> bool { storage_config_ = storage_config; git_cas_ = GitCAS::Open(repo_path, log_level); return static_cast(git_cas_); } /// \brief Replace all entries of the precomputed root with an exact root. /// \param root Root to be replaced. /// \param value Root to be used as a replacement. void SetPrecomputedRoot(PrecomputedRoot const& root, FileRoot const& value); [[nodiscard]] auto Info(std::string const& repo) const noexcept -> RepositoryInfo const* { if (auto const* data = Data(repo)) { return &data->info; } return nullptr; } [[nodiscard]] auto ReadBlobFromGitCAS( std::string const& hex_id, bool is_symlink, LogLevel log_failure = LogLevel::Warning) const noexcept -> std::optional { return git_cas_ ? git_cas_->ReadObject(hex_id, /*is_hex_id=*/true, /*as_valid_symlink=*/is_symlink, log_failure) : std::nullopt; } [[nodiscard]] auto ReadTreeFromGitCAS( std::string const& hex_id) const noexcept -> std::optional; [[nodiscard]] auto WorkspaceRoot(std::string const& repo) const noexcept -> FileRoot const* { return Get( repo, [](auto const& info) { return &info.workspace_root; }); } [[nodiscard]] auto TargetRoot(std::string const& repo) const noexcept -> FileRoot const* { return Get( repo, [](auto const& info) { return &info.target_root; }); } [[nodiscard]] auto RuleRoot(std::string const& repo) const -> FileRoot const* { return Get(repo, [](auto const& info) { return &info.rule_root; }); } [[nodiscard]] auto ExpressionRoot(std::string const& repo) const noexcept -> FileRoot const* { return Get( repo, [](auto const& info) { return &info.expression_root; }); } [[nodiscard]] auto GlobalName(std::string const& repo, std::string const& local_name) const noexcept -> std::string const* { return Get( repo, [&local_name](auto const& info) -> std::string const* { auto it = info.name_mapping.find(local_name); if (it != info.name_mapping.end()) { return &it->second; } return nullptr; }); } [[nodiscard]] auto TargetFileName(std::string const& repo) const noexcept -> std::string const* { return Get( repo, [](auto const& info) { return &info.target_file_name; }); } [[nodiscard]] auto RuleFileName(std::string const& repo) const noexcept -> std::string const* { return Get( repo, [](auto const& info) { return &info.rule_file_name; }); } [[nodiscard]] auto ExpressionFileName( std::string const& repo) const noexcept -> std::string const* { return Get( repo, [](auto const& info) { return &info.expression_file_name; }); } // Obtain repository's cache key if the repository is content fixed or // std::nullopt otherwise. [[nodiscard]] auto RepositoryKey(Storage const& storage, std::string const& repo) const noexcept -> std::optional; // used for testing void Reset() { repos_.clear(); git_cas_.reset(); duplicates_.Reset(); } private: using duplicates_t = std::unordered_map; // All data we store per repository. struct RepositoryData { // Info structure (roots, file names, bindings) RepositoryInfo info{}; // Base description if content-fixed std::optional base_desc; // Cache key if content-fixed AtomicValue> key; }; std::unordered_map repos_; GitCASPtr git_cas_; StorageConfig const* storage_config_ = nullptr; AtomicValue duplicates_; template [[nodiscard]] auto Get(std::string const& repo, std::function const& getter) const noexcept -> T const* { try { if (auto const* info = Info(repo)) { return getter(*info); } } catch (...) { return nullptr; }; return nullptr; } [[nodiscard]] auto Data(std::string const& repo) const noexcept -> RepositoryData const* { auto it = repos_.find(repo); if (it != repos_.end()) { return &it->second; } return nullptr; } [[nodiscard]] auto DeduplicateRepo(std::string const& repo, HashFunction hash_function) const -> std::string; [[nodiscard]] auto BuildGraphForRepository(std::string const& repo, HashFunction hash_function) const -> std::optional; [[nodiscard]] auto AddToGraphAndGetId( gsl::not_null const& graph, gsl::not_null const& id_counter, gsl::not_null*> const& repo_ids, std::string const& repo, HashFunction hash_function) const -> std::optional; }; #endif // INCLUDED_SRC_BUILDTOOL_COMMON_REPOSITORY_CONFIG_HPP