diff options
author | Klaus Aehlig <klaus.aehlig@huawei.com> | 2022-05-10 16:45:57 +0200 |
---|---|---|
committer | Klaus Aehlig <klaus.aehlig@huawei.com> | 2022-05-12 09:10:51 +0200 |
commit | ea21bce031d679e23c27814dc6e129f4e2b1fc00 (patch) | |
tree | f2ec24763752efea1d2598fc19bd603f653af821 /src/buildtool/build_engine/target_map/utils.cpp | |
parent | a79c1c5b8718347047ffbed4979c696d7a10484a (diff) | |
download | justbuild-ea21bce031d679e23c27814dc6e129f4e2b1fc00.tar.gz |
Ensure we also correctly handle tree conflicts between files
Not only trees, but also regular files can disallow paths reaching
into them. If we have a file at a/b then another file at a/b/c
is a staging conflict as well. Make our tool recognize this.
Diffstat (limited to 'src/buildtool/build_engine/target_map/utils.cpp')
-rw-r--r-- | src/buildtool/build_engine/target_map/utils.cpp | 38 |
1 files changed, 23 insertions, 15 deletions
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(); } } } |