diff options
Diffstat (limited to 'src/other_tools/utils/parse_archive.cpp')
-rw-r--r-- | src/other_tools/utils/parse_archive.cpp | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/src/other_tools/utils/parse_archive.cpp b/src/other_tools/utils/parse_archive.cpp new file mode 100644 index 00000000..ff5d20bf --- /dev/null +++ b/src/other_tools/utils/parse_archive.cpp @@ -0,0 +1,133 @@ +// 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/other_tools/utils/parse_archive.hpp" + +namespace { +auto ParseArchiveContent(ExpressionPtr const& repo_desc, + std::string const& origin, + const AsyncMapConsumerLoggerPtr& logger) + -> std::optional<ArchiveContent> { + + // enforce mandatory fields + auto repo_desc_content = repo_desc->At("content"); + if (not repo_desc_content) { + (*logger)("ArchiveCheckout: Mandatory field \"content\" is missing", + /*fatal=*/true); + return std::nullopt; + } + if (not repo_desc_content->get()->IsString()) { + (*logger)(fmt::format("ArchiveCheckout: Unsupported value {} for " + "mandatory field \"content\"", + repo_desc_content->get()->ToString()), + /*fatal=*/true); + return std::nullopt; + } + auto repo_desc_fetch = repo_desc->At("fetch"); + if (not repo_desc_fetch) { + (*logger)("ArchiveCheckout: Mandatory field \"fetch\" is missing", + /*fatal=*/true); + return std::nullopt; + } + if (not repo_desc_fetch->get()->IsString()) { + (*logger)(fmt::format("ArchiveCheckout: Unsupported value {} for " + "mandatory field \"fetch\"", + repo_desc_fetch->get()->ToString()), + /*fatal=*/true); + return std::nullopt; + } + auto repo_desc_distfile = repo_desc->Get("distfile", Expression::none_t{}); + auto repo_desc_sha256 = repo_desc->Get("sha256", Expression::none_t{}); + auto repo_desc_sha512 = repo_desc->Get("sha512", Expression::none_t{}); + // check optional mirrors + auto repo_desc_mirrors = repo_desc->Get("mirrors", Expression::list_t{}); + std::vector<std::string> mirrors{}; + if (repo_desc_mirrors->IsList()) { + mirrors.reserve(repo_desc_mirrors->List().size()); + for (auto const& elem : repo_desc_mirrors->List()) { + if (not elem->IsString()) { + (*logger)(fmt::format("ArchiveCheckout: Unsupported list entry " + "{} in optional field \"mirrors\"", + elem->ToString()), + /*fatal=*/true); + return std::nullopt; + } + mirrors.emplace_back(elem->String()); + } + } + else { + (*logger)(fmt::format("ArchiveCheckout: Optional field \"mirrors\" " + "should be a list of strings, but found: {}", + repo_desc_mirrors->ToString()), + /*fatal=*/true); + return std::nullopt; + } + + return ArchiveContent{ + .content = repo_desc_content->get()->String(), + .distfile = repo_desc_distfile->IsString() + ? std::make_optional(repo_desc_distfile->String()) + : std::nullopt, + .fetch_url = repo_desc_fetch->get()->String(), + .mirrors = std::move(mirrors), + .sha256 = repo_desc_sha256->IsString() + ? std::make_optional(repo_desc_sha256->String()) + : std::nullopt, + .sha512 = repo_desc_sha512->IsString() + ? std::make_optional(repo_desc_sha512->String()) + : std::nullopt, + .origin = origin}; +} +} // namespace + +auto ParseArchiveDescription(ExpressionPtr const& repo_desc, + std::string const& repo_type, + std::string const& origin, + const AsyncMapConsumerLoggerPtr& logger) + -> std::optional<ArchiveRepoInfo> { + auto archive_content = ParseArchiveContent(repo_desc, origin, logger); + if (not archive_content) { + return std::nullopt; + } + // additional mandatory fields + auto repo_desc_subdir = repo_desc->Get("subdir", Expression::none_t{}); + auto subdir = std::filesystem::path(repo_desc_subdir->IsString() + ? repo_desc_subdir->String() + : "") + .lexically_normal(); + + // check "special" pragma + auto repo_desc_pragma = repo_desc->At("pragma"); + bool const& pragma_is_map = + repo_desc_pragma and repo_desc_pragma->get()->IsMap(); + auto pragma_special = + pragma_is_map ? repo_desc_pragma->get()->At("special") : std::nullopt; + auto pragma_special_value = + pragma_special and pragma_special->get()->IsString() and + kPragmaSpecialMap.contains(pragma_special->get()->String()) + ? std::make_optional( + kPragmaSpecialMap.at(pragma_special->get()->String())) + : std::nullopt; + // check "absent" pragma + auto pragma_absent = + pragma_is_map ? repo_desc_pragma->get()->At("absent") : std::nullopt; + auto pragma_absent_value = pragma_absent and + pragma_absent->get()->IsBool() and + pragma_absent->get()->Bool(); + return ArchiveRepoInfo{.archive = *archive_content, + .repo_type = repo_type, + .subdir = subdir.empty() ? "." : subdir.string(), + .pragma_special = pragma_special_value, + .absent = pragma_absent_value}; +} |