diff options
author | Klaus Aehlig <klaus.aehlig@huawei.com> | 2024-02-27 16:34:30 +0100 |
---|---|---|
committer | Klaus Aehlig <klaus.aehlig@huawei.com> | 2024-03-05 11:05:10 +0100 |
commit | d90076c91f7aa83c35a8a0c3840048178dfc1e39 (patch) | |
tree | 571f8c8a603d360d6b52715fa6acb28d90dcdcc7 /src | |
parent | cae2ec50abedb135bbeab2aae95fecebcfe977b3 (diff) | |
download | justbuild-d90076c91f7aa83c35a8a0c3840048178dfc1e39.tar.gz |
Add data structure for foreign-file roots
Diffstat (limited to 'src')
-rw-r--r-- | src/other_tools/ops_maps/content_cas_map.hpp | 25 | ||||
-rw-r--r-- | src/other_tools/utils/TARGETS | 1 | ||||
-rw-r--r-- | src/other_tools/utils/parse_archive.cpp | 65 | ||||
-rw-r--r-- | src/other_tools/utils/parse_archive.hpp | 8 |
4 files changed, 99 insertions, 0 deletions
diff --git a/src/other_tools/ops_maps/content_cas_map.hpp b/src/other_tools/ops_maps/content_cas_map.hpp index d9462c68..d6ad0088 100644 --- a/src/other_tools/ops_maps/content_cas_map.hpp +++ b/src/other_tools/ops_maps/content_cas_map.hpp @@ -61,6 +61,18 @@ struct ArchiveRepoInfo { } }; +struct ForeignFileInfo { + ArchiveContent archive{}; /* key */ + std::string name{}; /* key */ + bool executable{}; /* key */ + bool absent{}; /* key */ + + [[nodiscard]] auto operator==(const ForeignFileInfo& other) const -> bool { + return archive == other.archive and name == other.name and + executable == other.executable and absent == other.absent; + } +}; + /// \brief Maps the content hash of an archive to nullptr, as we only care if /// the map fails or not. using ContentCASMap = AsyncMapConsumer<ArchiveContent, std::nullptr_t>; @@ -98,6 +110,19 @@ struct hash<ArchiveRepoInfo> { return seed; } }; + +template <> +struct hash<ForeignFileInfo> { + [[nodiscard]] auto operator()(const ForeignFileInfo& ct) const noexcept + -> std::size_t { + size_t seed{}; + hash_combine<ArchiveContent>(&seed, ct.archive); + hash_combine<std::string>(&seed, ct.name); + hash_combine<bool>(&seed, ct.executable); + hash_combine<bool>(&seed, ct.absent); + return seed; + } +}; } // namespace std #endif // INCLUDED_SRC_OTHER_TOOLS_OPS_MAPS_CONTENT_CAS_MAP_HPP diff --git a/src/other_tools/utils/TARGETS b/src/other_tools/utils/TARGETS index 27c4a6af..207dfb76 100644 --- a/src/other_tools/utils/TARGETS +++ b/src/other_tools/utils/TARGETS @@ -55,6 +55,7 @@ [ ["src/buildtool/build_engine/expression", "expression"] , ["src/other_tools/ops_maps", "content_cas_map"] ] + , "private-deps": [["@", "fmt", "", "fmt"]] , "stage": ["src", "other_tools", "utils"] } } diff --git a/src/other_tools/utils/parse_archive.cpp b/src/other_tools/utils/parse_archive.cpp index ff5d20bf..f0026eaa 100644 --- a/src/other_tools/utils/parse_archive.cpp +++ b/src/other_tools/utils/parse_archive.cpp @@ -14,6 +14,8 @@ #include "src/other_tools/utils/parse_archive.hpp" +#include "fmt/core.h" + namespace { auto ParseArchiveContent(ExpressionPtr const& repo_desc, std::string const& origin, @@ -89,6 +91,17 @@ auto ParseArchiveContent(ExpressionPtr const& repo_desc, : std::nullopt, .origin = origin}; } + +auto IsValidFileName(const std::string& s) -> bool { + if (s.find_first_of("/\0") != std::string::npos) { + return false; + } + if (s.empty() or s == "." or s == "..") { + return false; + } + return true; +} + } // namespace auto ParseArchiveDescription(ExpressionPtr const& repo_desc, @@ -131,3 +144,55 @@ auto ParseArchiveDescription(ExpressionPtr const& repo_desc, .pragma_special = pragma_special_value, .absent = pragma_absent_value}; } + +auto ParseForeignFileDescription(ExpressionPtr const& repo_desc, + std::string const& origin, + const AsyncMapConsumerLoggerPtr& logger) + -> std::optional<ForeignFileInfo> { + auto archive_content = ParseArchiveContent(repo_desc, origin, logger); + if (not archive_content) { + return std::nullopt; + } + auto name = repo_desc->At("name"); + if (not name) { + (*logger)( + "Mandatory field \"name\" for foreign file repository is missing", + true); + return std::nullopt; + } + if (not name->get()->IsString()) { + (*logger)(fmt::format("Field \"name\" has to be a file name, given as " + "string, but found {}", + name->get()->ToString()), + true); + return std::nullopt; + } + if (not IsValidFileName(name->get()->String())) { + (*logger)(fmt::format("Field \"name\" has to be valid a file name, but " + "found {}", + name->get()->ToString()), + true); + return std::nullopt; + } + auto executable = repo_desc->Get("executable", Expression::kFalse); + if (not executable->IsBool()) { + (*logger)(fmt::format( + "Field \"executable\" has to be a boolean, but found {}", + executable->ToString()), + true); + return std::nullopt; + } + bool absent{}; + auto pragma = repo_desc->Get("pragma", Expression::kEmptyMap); + if (pragma->IsMap()) { + auto pragma_absent = pragma->Get("absent", Expression::kFalse); + if (pragma_absent->IsBool()) { + absent = pragma_absent->Bool(); + } + } + + return ForeignFileInfo{.archive = *archive_content, + .name = name->get()->String(), + .executable = executable->Bool(), + .absent = absent}; +} diff --git a/src/other_tools/utils/parse_archive.hpp b/src/other_tools/utils/parse_archive.hpp index 91f3e280..6d356dd4 100644 --- a/src/other_tools/utils/parse_archive.hpp +++ b/src/other_tools/utils/parse_archive.hpp @@ -30,4 +30,12 @@ auto ParseArchiveDescription(ExpressionPtr const& repo_desc, const AsyncMapConsumerLoggerPtr& logger) -> std::optional<ArchiveRepoInfo>; +// Parse the description of a foreign-file repository; if an error +// occurs, call the logger with fatal set to true and return std::nullopt +// instead. +auto ParseForeignFileDescription(ExpressionPtr const& repo_desc, + std::string const& origin, + const AsyncMapConsumerLoggerPtr& logger) + -> std::optional<ForeignFileInfo>; + #endif |