summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/buildtool/build_engine/target_map/TARGETS8
-rw-r--r--src/buildtool/build_engine/target_map/target_map.cpp13
-rw-r--r--src/buildtool/build_engine/target_map/utils.cpp38
3 files changed, 31 insertions, 28 deletions
diff --git a/src/buildtool/build_engine/target_map/TARGETS b/src/buildtool/build_engine/target_map/TARGETS
index 9dca513d..3854039c 100644
--- a/src/buildtool/build_engine/target_map/TARGETS
+++ b/src/buildtool/build_engine/target_map/TARGETS
@@ -49,4 +49,12 @@
]
, "stage": ["src", "buildtool", "build_engine", "target_map"]
}
+, "target_map_testable_internals":
+ { "type": ["@", "rules", "CC", "library"]
+ , "tainted": ["test"]
+ , "name": ["target_map_testable_internals"]
+ , "hdrs": ["utils.hpp"]
+ , "deps": ["target_map"]
+ , "stage": ["src", "buildtool", "build_engine", "target_map"]
+ }
}
diff --git a/src/buildtool/build_engine/target_map/target_map.cpp b/src/buildtool/build_engine/target_map/target_map.cpp
index 2f5df0b5..4f4a087b 100644
--- a/src/buildtool/build_engine/target_map/target_map.cpp
+++ b/src/buildtool/build_engine/target_map/target_map.cpp
@@ -554,19 +554,6 @@ void withDependencies(
}
auto norm_path =
ToNormalPath(std::filesystem::path{input_path});
- if (norm_path == "." or norm_path.empty()) {
- if (val->Map().size() > 1) {
- throw Evaluator::EvaluationError{
- "input path '.' or '' for TREE is only allowed "
- "for trees with single input artifact"};
- }
- if (not artifact->Artifact().IsTree()) {
- throw Evaluator::EvaluationError{
- "input path '.' or '' for TREE must be tree "
- "artifact"};
- }
- return artifact;
- }
artifacts.emplace(std::move(norm_path), artifact->Artifact());
}
auto conflict = BuildMaps::Target::Utils::tree_conflict(val);
diff --git a/src/buildtool/build_engine/target_map/utils.cpp b/src/buildtool/build_engine/target_map/utils.cpp
index bdd5dd11..4dcafa4f 100644
--- a/src/buildtool/build_engine/target_map/utils.cpp
+++ b/src/buildtool/build_engine/target_map/utils.cpp
@@ -2,6 +2,7 @@
#include <algorithm>
#include <filesystem>
+#include <unordered_set>
#include <vector>
#include "src/utils/cpp/path.hpp"
@@ -91,23 +92,30 @@ auto BuildMaps::Target::Utils::artifacts_tree(const ExpressionPtr& map)
auto BuildMaps::Target::Utils::tree_conflict(const ExpressionPtr& map)
-> std::optional<std::string> {
- std::vector<std::filesystem::path> trees{};
- for (auto const& [path, artifact] : map->Map()) {
- if (artifact->Artifact().IsTree()) {
- trees.emplace_back(ToNormalPath(std::filesystem::path{path}));
+ // Work around the fact that std::hash<std::filesystem::path> is missing
+ // in some libraries
+ struct PathHash {
+ auto operator()(std::filesystem::path const& p) const noexcept
+ -> std::size_t {
+ return std::filesystem::hash_value(p);
}
- }
- if (trees.empty()) {
- return std::nullopt;
- }
+ };
+ std::unordered_set<std::filesystem::path, PathHash> blocked{};
+ blocked.reserve(map->Map().size());
+
for (auto const& [path, artifact] : map->Map()) {
- auto p = ToNormalPath(std::filesystem::path{path});
- for (auto const& treepath : trees) {
- if (not artifact->Artifact().IsTree()) {
- if (std::mismatch(treepath.begin(), treepath.end(), p.begin())
- .first == treepath.end()) {
- return path;
- }
+ if (path == "." and map->Map().size() > 1) {
+ return ".";
+ }
+ auto p = std::filesystem::path{path};
+ auto insert_result = blocked.insert(p);
+ if (not insert_result.second) {
+ return p.string(); // duplicate path
+ }
+ for (p = p.parent_path(); not p.empty(); p = p.parent_path()) {
+ if (blocked.contains(p)) {
+ // Another artifact at a parent path position
+ return p.string();
}
}
}