diff options
Diffstat (limited to 'src/buildtool/file_system/file_root.hpp')
-rw-r--r-- | src/buildtool/file_system/file_root.hpp | 98 |
1 files changed, 97 insertions, 1 deletions
diff --git a/src/buildtool/file_system/file_root.hpp b/src/buildtool/file_system/file_root.hpp index 4fb587c2..5db6ed82 100644 --- a/src/buildtool/file_system/file_root.hpp +++ b/src/buildtool/file_system/file_root.hpp @@ -16,6 +16,7 @@ #define INCLUDED_SRC_BUILDTOOL_FILE_SYSTEM_FILE_ROOT_HPP #include <algorithm> +#include <compare> #include <cstddef> #include <exception> #include <filesystem> @@ -45,6 +46,7 @@ #include "src/buildtool/logging/logger.hpp" #include "src/utils/cpp/concepts.hpp" #include "src/utils/cpp/expected.hpp" +#include "src/utils/cpp/hash_combine.hpp" // Keep it to ensure fmt::format works on JSON objects #include "src/utils/cpp/json.hpp" // IWYU pragma: keep @@ -110,15 +112,49 @@ class FileRoot { gsl::not_null<GitCASPtr> cas; gsl::not_null<GitTreePtr> tree; }; + + public: + struct ComputedRoot { + std::string repository; + std::string target_module; + std::string target_name; + nlohmann::json config; + + [[nodiscard]] auto operator==( + ComputedRoot const& other) const noexcept { + return (repository == other.repository) and + (target_module == other.target_module) and + (target_name == other.target_name) and + (config == other.config); + } + + [[nodiscard]] auto operator<(ComputedRoot const& other) const noexcept { + if (auto const res = repository <=> other.repository; res != 0) { + return res < 0; + } + if (auto const res = target_module <=> other.target_module; + res != 0) { + return res < 0; + } + if (auto const res = target_name <=> other.target_name; res != 0) { + return res < 0; + } + return config < other.config; + } + }; + + private: // absent roots are defined by a tree hash with no witnessing repository using absent_root_t = std::string; - using root_t = std::variant<fs_root_t, RootGit, absent_root_t>; + using root_t = + std::variant<fs_root_t, RootGit, absent_root_t, ComputedRoot>; public: static constexpr auto kGitTreeMarker = "git tree"; static constexpr auto kGitTreeIgnoreSpecialMarker = "git tree ignore-special"; static constexpr auto kFileIgnoreSpecialMarker = "file ignore-special"; + static constexpr auto kComputedMarker = "computed"; class DirectoryEntries { friend class FileRoot; @@ -335,6 +371,14 @@ class FileRoot { gsl::not_null<GitTreePtr> const& tree, bool ignore_special = false) noexcept : root_{RootGit{cas, tree}}, ignore_special_{ignore_special} {} + FileRoot(std::string repository, + std::string target_module, + std::string target_name, + nlohmann::json config) noexcept + : root_{ComputedRoot{std::move(repository), + std::move(target_module), + std::move(target_name), + std::move(config)}} {} [[nodiscard]] static auto FromGit(std::filesystem::path const& repo_path, std::string const& git_tree_id, @@ -635,6 +679,22 @@ class FileRoot { return std::nullopt; } + [[nodiscard]] auto IsComputed() const noexcept -> bool { + return std::holds_alternative<ComputedRoot>(root_); + } + + [[nodiscard]] auto GetComputedDescription() const noexcept + -> std::optional<ComputedRoot> { + if (std::holds_alternative<ComputedRoot>(root_)) { + try { + return std::get<ComputedRoot>(root_); + } catch (...) { + return std::nullopt; + } + } + return std::nullopt; + } + [[nodiscard]] auto IgnoreSpecial() const noexcept -> bool { return ignore_special_; } @@ -747,6 +807,27 @@ class FileRoot { FileRoot{std::string{root[1]}, /*ignore_special=*/true}, std::nullopt); } + if (root[0] == FileRoot::kComputedMarker) { + // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) + if (root.size() != 5 or (not root[1].is_string()) or + (not root[2].is_string()) or (not root[3].is_string()) or + (not root[4].is_object())) { + *error_msg = fmt::format( + "{} scheme requires, in this order, the arugments root, " + "module, name, config. However found {} for {} of " + "repository {}", + kComputedMarker, + root.dump(), + keyword, + repo); + return std::nullopt; + } + return std::pair(FileRoot{std::string{root[1]}, + std::string{root[2]}, + std::string{root[3]}, + root[4]}, + std::nullopt); + } *error_msg = fmt::format( "Unknown scheme in the specification {} of {} of repository {}", root.dump(), @@ -763,4 +844,19 @@ class FileRoot { bool ignore_special_{}; }; +namespace std { +template <> +struct hash<FileRoot::ComputedRoot> { + [[nodiscard]] auto operator()(FileRoot::ComputedRoot const& cr) const + -> std::size_t { + size_t seed{}; + hash_combine<std::string>(&seed, cr.repository); + hash_combine<std::string>(&seed, cr.target_module); + hash_combine<std::string>(&seed, cr.target_name); + hash_combine<nlohmann::json>(&seed, cr.config); + return seed; + } +}; +} // namespace std + #endif // INCLUDED_SRC_BUILDTOOL_FILE_SYSTEM_FILE_ROOT_HPP |