diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/buildtool/build_engine/target_map/TARGETS | 8 | ||||
-rw-r--r-- | src/buildtool/build_engine/target_map/target_map.cpp | 13 | ||||
-rw-r--r-- | src/buildtool/build_engine/target_map/utils.cpp | 38 |
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(); } } } |