summaryrefslogtreecommitdiff
path: root/src/buildtool/file_system/file_root.hpp
diff options
context:
space:
mode:
authorPaul Cristian Sarbu <paul.cristian.sarbu@huawei.com>2023-05-23 15:19:28 +0200
committerPaul Cristian Sarbu <paul.cristian.sarbu@huawei.com>2023-05-31 15:21:02 +0200
commitbc93b16bf6eccf23d7018444872867f97f5dc94d (patch)
tree412c03a39f98eec84d98ab10f0af3ab586d6c7e6 /src/buildtool/file_system/file_root.hpp
parentda9c8f50b1a841830f3323f0438de2f3a0974022 (diff)
downloadjustbuild-bc93b16bf6eccf23d7018444872867f97f5dc94d.tar.gz
FileRoot: Add ignore-special roots logic
Diffstat (limited to 'src/buildtool/file_system/file_root.hpp')
-rw-r--r--src/buildtool/file_system/file_root.hpp50
1 files changed, 39 insertions, 11 deletions
diff --git a/src/buildtool/file_system/file_root.hpp b/src/buildtool/file_system/file_root.hpp
index e25a2455..af61c8fd 100644
--- a/src/buildtool/file_system/file_root.hpp
+++ b/src/buildtool/file_system/file_root.hpp
@@ -209,6 +209,9 @@ class FileRoot {
return true;
}
+ /// \brief Retrieve a root tree as a KNOWN artifact.
+ /// User should know whether this root tree is symlink free and only
+ /// call this function accordingly.
[[nodiscard]] auto AsKnownTree(std::string const& repository)
const noexcept -> std::optional<ArtifactDescription> {
if (Compatibility::IsCompatible()) {
@@ -270,20 +273,30 @@ class FileRoot {
};
FileRoot() noexcept = default;
+ explicit FileRoot(bool ignore_special) noexcept
+ : ignore_special_(ignore_special) {}
+ // avoid type narrowing errors
+ explicit FileRoot(char const* root) noexcept : root_{fs_root_t{root}} {}
explicit FileRoot(std::filesystem::path root) noexcept
: root_{std::move(root)} {}
+ FileRoot(std::filesystem::path root, bool ignore_special) noexcept
+ : root_{std::move(root)}, ignore_special_{ignore_special} {}
FileRoot(gsl::not_null<GitCASPtr> const& cas,
- gsl::not_null<GitTreePtr> const& tree) noexcept
- : root_{git_root_t{cas, tree}} {}
+ gsl::not_null<GitTreePtr> const& tree,
+ bool ignore_special = false) noexcept
+ : root_{git_root_t{cas, tree}}, ignore_special_{ignore_special} {}
[[nodiscard]] static auto FromGit(std::filesystem::path const& repo_path,
- std::string const& git_tree_id) noexcept
+ std::string const& git_tree_id,
+ bool ignore_special = false) noexcept
-> std::optional<FileRoot> {
if (auto cas = GitCAS::Open(repo_path)) {
- if (auto tree = GitTree::Read(cas, git_tree_id)) {
+ if (auto tree = GitTree::Read(cas, git_tree_id, ignore_special)) {
try {
return FileRoot{
- cas, std::make_shared<GitTree const>(std::move(*tree))};
+ cas,
+ std::make_shared<GitTree const>(std::move(*tree)),
+ ignore_special};
} catch (...) {
}
}
@@ -291,13 +304,14 @@ class FileRoot {
return std::nullopt;
}
- // Return a complete description of the content of this root, if that can be
- // done without any file-system access.
+ // Return a complete description of the content of this root, if
+ // content-fixed.
[[nodiscard]] auto ContentDescription() const noexcept
-> std::optional<nlohmann::json> {
try {
if (std::holds_alternative<git_root_t>(root_)) {
nlohmann::json j;
+ // ignore-special git-tree-based roots are still content-fixed
j.push_back(kGitTreeMarker);
j.push_back(std::get<git_root_t>(root_).tree->Hash());
return j;
@@ -323,7 +337,12 @@ class FileRoot {
return static_cast<bool>(
std::get<git_root_t>(root_).tree->LookupEntryByPath(path));
}
- return FileSystemManager::Exists(std::get<fs_root_t>(root_) / path);
+ // std::holds_alternative<fs_root_t>(root_) == true
+ auto root_path = std::get<fs_root_t>(root_) / path;
+ auto exists = FileSystemManager::Exists(root_path);
+ return (ignore_special_ ? exists and FileSystemManager::Type(
+ root_path) != std::nullopt
+ : exists);
}
[[nodiscard]] auto IsFile(
@@ -380,7 +399,7 @@ class FileRoot {
return DirectoryEntries{&(*tree)};
}
if (auto entry = tree->LookupEntryByPath(dir_path)) {
- if (auto const& found_tree = entry->Tree()) {
+ if (auto const& found_tree = entry->Tree(ignore_special_)) {
return DirectoryEntries{&(*found_tree)};
}
}
@@ -392,7 +411,8 @@ class FileRoot {
[&map](const auto& name, auto type) {
map.emplace(name.string(), type);
return true;
- })) {
+ },
+ ignore_special_)) {
return DirectoryEntries{std::move(map)};
}
}
@@ -425,6 +445,7 @@ class FileRoot {
return std::nullopt;
}
+ /// \brief Read a blob from the root based on its ID.
[[nodiscard]] auto ReadBlob(std::string const& blob_id) const noexcept
-> std::optional<std::string> {
if (std::holds_alternative<git_root_t>(root_)) {
@@ -434,9 +455,12 @@ class FileRoot {
return std::nullopt;
}
+ /// \brief Read a root tree based on its ID.
+ /// User should know whether the desired tree is symlink free and only call
+ /// this function accordingly.
[[nodiscard]] auto ReadTree(std::string const& tree_id) const noexcept
-> std::optional<GitTree> {
- if (std::holds_alternative<git_root_t>(root_)) {
+ if (std::holds_alternative<git_root_t>(root_) and not ignore_special_) {
try {
auto const& cas = std::get<git_root_t>(root_).cas;
return GitTree::Read(cas, tree_id);
@@ -481,6 +505,10 @@ class FileRoot {
private:
root_t root_;
+ // If set, forces lookups to ignore entries which are neither file nor
+ // directories instead of erroring out. This means implicitly also that
+ // there are no more fast tree lookups, i.e., tree traversal is a must.
+ bool ignore_special_{};
};
#endif // INCLUDED_SRC_BUILDTOOL_FILE_SYSTEM_FILE_ROOT_HPP