summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/buildtool/file_system/file_root.hpp119
-rw-r--r--test/buildtool/build_engine/target_map/target_map.test.cpp14
-rw-r--r--test/buildtool/common/repository_config.test.cpp4
-rwxr-xr-xtest/buildtool/execution_engine/executor/executor_api.test.hpp4
-rw-r--r--test/buildtool/file_system/file_root.test.cpp8
5 files changed, 105 insertions, 44 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:
diff --git a/test/buildtool/build_engine/target_map/target_map.test.cpp b/test/buildtool/build_engine/target_map/target_map.test.cpp
index bd868b48..6397ba1d 100644
--- a/test/buildtool/build_engine/target_map/target_map.test.cpp
+++ b/test/buildtool/build_engine/target_map/target_map.test.cpp
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <filesystem>
+
#include "catch2/catch_test_macros.hpp"
#include "src/buildtool/build_engine/base_maps/directory_map.hpp"
#include "src/buildtool/build_engine/base_maps/entity_name.hpp"
@@ -47,10 +49,14 @@ void SetupConfig() {
[[maybe_unused]] static auto done = CreateSymlinks();
// create the file roots
auto info = RepositoryConfig::RepositoryInfo{
- FileRoot{"test/buildtool/build_engine/target_map/data_src"},
- FileRoot{"test/buildtool/build_engine/target_map/data_targets"},
- FileRoot{"test/buildtool/build_engine/target_map/data_rules"},
- FileRoot{"test/buildtool/build_engine/target_map/data_expr"}};
+ FileRoot{std::filesystem::path{"test/buildtool/build_engine/target_map/"
+ "data_src"}},
+ FileRoot{std::filesystem::path{"test/buildtool/build_engine/target_map/"
+ "data_targets"}},
+ FileRoot{std::filesystem::path{"test/buildtool/build_engine/target_map/"
+ "data_rules"}},
+ FileRoot{std::filesystem::path{"test/buildtool/build_engine/target_map/"
+ "data_expr"}}};
RepositoryConfig::Instance().Reset();
RepositoryConfig::Instance().SetInfo("", std::move(info));
}
diff --git a/test/buildtool/common/repository_config.test.cpp b/test/buildtool/common/repository_config.test.cpp
index 29c89d50..cfde95ed 100644
--- a/test/buildtool/common/repository_config.test.cpp
+++ b/test/buildtool/common/repository_config.test.cpp
@@ -43,7 +43,7 @@ namespace {
return std::move(*root);
}
}
- return FileRoot{"missing"};
+ return FileRoot{std::filesystem::path{"missing"}};
}
[[nodiscard]] auto CreateFixedRepoInfo(
@@ -61,7 +61,7 @@ namespace {
std::string const& tfn = "TARGETS",
std::string const& rfn = "RULES",
std::string const& efn = "EXPRESSIONS") {
- static auto const kFileRoot = FileRoot{"file path"};
+ static auto const kFileRoot = FileRoot{std::filesystem::path{"file path"}};
return RepositoryConfig::RepositoryInfo{
kFileRoot, kFileRoot, kFileRoot, kFileRoot, bindings, tfn, rfn, efn};
}
diff --git a/test/buildtool/execution_engine/executor/executor_api.test.hpp b/test/buildtool/execution_engine/executor/executor_api.test.hpp
index ffee5184..bd02e0fb 100755
--- a/test/buildtool/execution_engine/executor/executor_api.test.hpp
+++ b/test/buildtool/execution_engine/executor/executor_api.test.hpp
@@ -31,8 +31,8 @@
using ApiFactory = std::function<IExecutionApi::Ptr()>;
static inline void SetupConfig() {
- auto info = RepositoryConfig::RepositoryInfo{
- FileRoot{"test/buildtool/execution_engine/executor"}};
+ auto info = RepositoryConfig::RepositoryInfo{FileRoot{
+ std::filesystem::path{"test/buildtool/execution_engine/executor"}}};
RepositoryConfig::Instance().SetInfo("", std::move(info));
}
diff --git a/test/buildtool/file_system/file_root.test.cpp b/test/buildtool/file_system/file_root.test.cpp
index eab17ff6..8828fb7b 100644
--- a/test/buildtool/file_system/file_root.test.cpp
+++ b/test/buildtool/file_system/file_root.test.cpp
@@ -165,7 +165,8 @@ TEST_CASE("Creating file root", "[file_root]") {
REQUIRE(root_path);
CHECK(FileRoot{*root_path}.Exists("."));
- CHECK_FALSE(FileRoot{"does_not_exist"}.Exists("."));
+ CHECK_FALSE(
+ FileRoot{std::filesystem::path{"does_not_exist"}}.Exists("."));
}
SECTION("git root") {
@@ -184,8 +185,9 @@ TEST_CASE("Creating file root", "[file_root]") {
REQUIRE(root_path);
CHECK(FileRoot{*root_path, /*ignore_special=*/true}.Exists("."));
- CHECK_FALSE(
- FileRoot{"does_not_exist", /*ignore_special=*/true}.Exists("."));
+ CHECK_FALSE(FileRoot{std::filesystem::path{"does_not_exist"},
+ /*ignore_special=*/true}
+ .Exists("."));
}
SECTION("git root ignore-special") {