summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Cristian Sarbu <paul.cristian.sarbu@huawei.com>2023-10-24 15:25:27 +0200
committerAlberto Sartori <alberto.sartori@huawei.com>2023-11-15 20:19:18 +0100
commit981b9b10d6f48fb2768110a9f81a5f4e880406b2 (patch)
tree9d3afb2e9c65862fe70cc1e476b5f4ae87e45183 /src
parentfe907ca625657dce0e2f08f2129cf36c840602d3 (diff)
downloadjustbuild-981b9b10d6f48fb2768110a9f81a5f4e880406b2.tar.gz
FileRoot: Add new absent root underlying type variant
Absent roots are characterised only by a Git tree hash, so a new variant of the underlying stored information was added in the form of a plain string. In order to avoid unwanted implicit conversions when instantiating via literal strings, we force callers of the constructors to explicitly differentiate between plain strings and filesystem paths. Existing tests were updated to reflect this. Co-authored-by: Alberto Sartori <alberto.sartori@huawei.com>
Diffstat (limited to 'src')
-rw-r--r--src/buildtool/file_system/file_root.hpp119
1 files changed, 86 insertions, 33 deletions
diff --git a/src/buildtool/file_system/file_root.hpp b/src/buildtool/file_system/file_root.hpp
index feb5519a..4d07f938 100644
--- a/src/buildtool/file_system/file_root.hpp
+++ b/src/buildtool/file_system/file_root.hpp
@@ -94,7 +94,9 @@ class FileRoot {
gsl::not_null<GitCASPtr> cas;
gsl::not_null<GitTreePtr> tree;
};
- using root_t = std::variant<fs_root_t, git_root_t>;
+ // 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, git_root_t, absent_root_t>;
public:
static constexpr auto kGitTreeMarker = "git tree";
@@ -297,12 +299,24 @@ 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}} {}
+ // avoid type narrowing errors, but force explicit choice of underlying type
+ explicit FileRoot(char const* /*root*/) noexcept {
+ Logger::Log(LogLevel::Error,
+ "FileRoot object instantiation must be explicit!");
+ }
+ explicit FileRoot(char const* /*root*/, bool /*ignore_special*/) noexcept {
+ Logger::Log(LogLevel::Error,
+ "FileRoot object instantiation must be explicit!");
+ }
+ explicit FileRoot(std::string root) noexcept
+ : root_{absent_root_t{std::move(root)}} {}
+ explicit FileRoot(std::string root, bool ignore_special) noexcept
+ : root_{absent_root_t{std::move(root)}},
+ ignore_special_{ignore_special} {}
explicit FileRoot(std::filesystem::path root) noexcept
- : root_{std::move(root)} {}
+ : root_{fs_root_t{std::move(root)}} {}
FileRoot(std::filesystem::path root, bool ignore_special) noexcept
- : root_{std::move(root)}, ignore_special_{ignore_special} {}
+ : root_{fs_root_t{std::move(root)}}, ignore_special_{ignore_special} {}
FileRoot(gsl::not_null<GitCASPtr> const& cas,
gsl::not_null<GitTreePtr> const& tree,
bool ignore_special = false) noexcept
@@ -338,6 +352,13 @@ class FileRoot {
j.push_back(std::get<git_root_t>(root_).tree->Hash());
return j;
}
+ if (std::holds_alternative<absent_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<absent_root_t>(root_));
+ return j;
+ }
} catch (...) {
}
return std::nullopt;
@@ -359,12 +380,16 @@ class FileRoot {
return static_cast<bool>(
std::get<git_root_t>(root_).tree->LookupEntryByPath(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);
- auto type = FileSystemManager::Type(root_path, /*allow_upwards=*/true);
- return (ignore_special_ ? exists and type and IsNonSpecialObject(*type)
- : exists);
+ if (std::holds_alternative<fs_root_t>(root_)) {
+ auto root_path = std::get<fs_root_t>(root_) / path;
+ auto exists = FileSystemManager::Exists(root_path);
+ auto type =
+ FileSystemManager::Type(root_path, /*allow_upwards=*/true);
+ return (ignore_special_
+ ? exists and type and IsNonSpecialObject(*type)
+ : exists);
+ }
+ return false; // absent roots cannot be interrogated locally
}
[[nodiscard]] auto IsFile(
@@ -375,10 +400,12 @@ class FileRoot {
file_path)) {
return IsFileObject(entry->Type());
}
- return false;
}
- return FileSystemManager::IsFile(std::get<fs_root_t>(root_) /
- file_path);
+ else if (std::holds_alternative<fs_root_t>(root_)) {
+ return FileSystemManager::IsFile(std::get<fs_root_t>(root_) /
+ file_path);
+ }
+ return false; // absent roots cannot be interrogated locally
}
[[nodiscard]] auto IsSymlink(
@@ -389,10 +416,12 @@ class FileRoot {
file_path)) {
return IsSymlinkObject(entry->Type());
}
- return false;
}
- return FileSystemManager::IsNonUpwardsSymlink(
- std::get<fs_root_t>(root_) / file_path);
+ else if (std::holds_alternative<fs_root_t>(root_)) {
+ return FileSystemManager::IsNonUpwardsSymlink(
+ std::get<fs_root_t>(root_) / file_path);
+ }
+ return false; // absent roots cannot be interrogated locally
}
[[nodiscard]] auto IsBlob(
@@ -411,10 +440,12 @@ class FileRoot {
dir_path)) {
return entry->IsTree();
}
- return false;
}
- return FileSystemManager::IsDirectory(std::get<fs_root_t>(root_) /
- dir_path);
+ else if (std::holds_alternative<fs_root_t>(root_)) {
+ return FileSystemManager::IsDirectory(std::get<fs_root_t>(root_) /
+ dir_path);
+ }
+ return false; // absent roots cannot be interrogated locally
}
/// \brief Read content of file or symlink.
@@ -428,14 +459,15 @@ class FileRoot {
return entry->Blob();
}
}
- return std::nullopt;
}
- auto full_path = std::get<fs_root_t>(root_) / file_path;
- if (auto type =
- FileSystemManager::Type(full_path, /*allow_upwards=*/true)) {
- return IsSymlinkObject(*type)
- ? FileSystemManager::ReadSymlink(full_path)
- : FileSystemManager::ReadFile(full_path);
+ else if (std::holds_alternative<fs_root_t>(root_)) {
+ auto full_path = std::get<fs_root_t>(root_) / file_path;
+ if (auto type = FileSystemManager::Type(full_path,
+ /*allow_upwards=*/true)) {
+ return IsSymlinkObject(*type)
+ ? FileSystemManager::ReadSymlink(full_path)
+ : FileSystemManager::ReadFile(full_path);
+ }
}
return std::nullopt;
}
@@ -454,7 +486,7 @@ class FileRoot {
}
}
}
- else {
+ else if (std::holds_alternative<fs_root_t>(root_)) {
DirectoryEntries::pairs_t map{};
if (FileSystemManager::ReadDirectory(
std::get<fs_root_t>(root_) / dir_path,
@@ -488,10 +520,12 @@ class FileRoot {
}
return std::nullopt;
}
- auto type = FileSystemManager::Type(
- std::get<fs_root_t>(root_) / file_path, /*allow_upwards=*/true);
- if (type and IsBlobObject(*type)) {
- return type;
+ if (std::holds_alternative<fs_root_t>(root_)) {
+ auto type = FileSystemManager::Type(
+ std::get<fs_root_t>(root_) / file_path, /*allow_upwards=*/true);
+ if (type and IsBlobObject(*type)) {
+ return type;
+ }
}
return std::nullopt;
}
@@ -550,7 +584,26 @@ class FileRoot {
}
return std::nullopt;
}
- return ArtifactDescription{file_path, repository};
+ if (std::holds_alternative<fs_root_t>(root_)) {
+ return ArtifactDescription{file_path, repository};
+ }
+ return std::nullopt; // absent roots are neither LOCAL nor KNOWN
+ }
+
+ [[nodiscard]] inline auto IsAbsent() const noexcept -> bool {
+ return std::holds_alternative<absent_root_t>(root_);
+ }
+
+ [[nodiscard]] inline auto GetAbsentTreeId() const noexcept
+ -> std::optional<std::string> {
+ if (std::holds_alternative<absent_root_t>(root_)) {
+ try {
+ return std::get<absent_root_t>(root_);
+ } catch (...) {
+ return std::nullopt;
+ }
+ }
+ return std::nullopt;
}
private: