summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKlaus Aehlig <klaus.aehlig@huawei.com>2024-02-27 16:34:30 +0100
committerKlaus Aehlig <klaus.aehlig@huawei.com>2024-03-05 11:05:10 +0100
commitd90076c91f7aa83c35a8a0c3840048178dfc1e39 (patch)
tree571f8c8a603d360d6b52715fa6acb28d90dcdcc7 /src
parentcae2ec50abedb135bbeab2aae95fecebcfe977b3 (diff)
downloadjustbuild-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.hpp25
-rw-r--r--src/other_tools/utils/TARGETS1
-rw-r--r--src/other_tools/utils/parse_archive.cpp65
-rw-r--r--src/other_tools/utils/parse_archive.hpp8
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