summaryrefslogtreecommitdiff
path: root/src/buildtool/build_engine/target_map/utils.cpp
diff options
context:
space:
mode:
authorKlaus Aehlig <klaus.aehlig@huawei.com>2022-05-10 16:45:57 +0200
committerKlaus Aehlig <klaus.aehlig@huawei.com>2022-05-12 09:10:51 +0200
commitea21bce031d679e23c27814dc6e129f4e2b1fc00 (patch)
treef2ec24763752efea1d2598fc19bd603f653af821 /src/buildtool/build_engine/target_map/utils.cpp
parenta79c1c5b8718347047ffbed4979c696d7a10484a (diff)
downloadjustbuild-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.cpp38
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();
}
}
}