summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/buildtool/file_system/TARGETS1
-rw-r--r--src/buildtool/file_system/file_root.hpp98
2 files changed, 98 insertions, 1 deletions
diff --git a/src/buildtool/file_system/TARGETS b/src/buildtool/file_system/TARGETS
index 59998b69..4dba0e72 100644
--- a/src/buildtool/file_system/TARGETS
+++ b/src/buildtool/file_system/TARGETS
@@ -189,6 +189,7 @@
, ["src/buildtool/logging", "logging"]
, ["src/utils/cpp", "concepts"]
, ["src/utils/cpp", "expected"]
+ , ["src/utils/cpp", "hash_combine"]
, ["src/utils/cpp", "json"]
]
, "stage": ["src", "buildtool", "file_system"]
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