diff options
author | Klaus Aehlig <klaus.aehlig@huawei.com> | 2024-08-02 12:00:44 +0200 |
---|---|---|
committer | Klaus Aehlig <klaus.aehlig@huawei.com> | 2024-08-02 14:09:02 +0200 |
commit | b2f795e0e05743a234587f3a1c32c9c1d4ec524f (patch) | |
tree | c5eecfc0d37fd9e581cc5dccb3c93a8482cb0e72 /src/buildtool/build_engine/target_map/utils.cpp | |
parent | 217da1d00c8fd8351d79587f7394e1ca8f498cff (diff) | |
download | justbuild-b2f795e0e05743a234587f3a1c32c9c1d4ec524f.tar.gz |
Actions with non-trivial cwd: add empty input tree, if required
While our local action execution implicitly creates the specified
cwd with the first output file or directory, this behaviour is
not mandated by the remote-execution protocol. There, an action
definition has to ensure that cwd is a directory implied by the
input files. Achieve this, by adding an empty input directory
at cwd if this can be done without creating tree conflicts.
Diffstat (limited to 'src/buildtool/build_engine/target_map/utils.cpp')
-rw-r--r-- | src/buildtool/build_engine/target_map/utils.cpp | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/src/buildtool/build_engine/target_map/utils.cpp b/src/buildtool/build_engine/target_map/utils.cpp index 71defc4c..c4f19248 100644 --- a/src/buildtool/build_engine/target_map/utils.cpp +++ b/src/buildtool/build_engine/target_map/utils.cpp @@ -149,6 +149,47 @@ auto BuildMaps::Target::Utils::tree_conflict(const ExpressionPtr& map) return std::nullopt; } +auto BuildMaps::Target::Utils::add_dir_for( + const std::string& cwd, + ExpressionPtr stage, + gsl::not_null<std::vector<Tree::Ptr>*> trees) -> ExpressionPtr { + // if working top-level, there is nothing to add; this is also + // the common case + if ((cwd.empty()) or (cwd == ".")) { + return stage; + } + auto cwd_path = std::filesystem::path{cwd}; + for (auto const& [path, artifact] : stage->Map()) { + if ((path.empty()) or (path == ".")) { + // top-level artifact (tree); cannot add tree for cwd + return stage; + } + auto p = std::filesystem::path{path}; + for (auto c = cwd_path; not c.empty(); c = c.parent_path()) { + if (c == p) { + // adding cwd would add a tree conflict; so nothing to add + return stage; + } + } + for (; not p.empty(); p = p.parent_path()) { + if (p == cwd_path) { + // adding cwd would add a tree conflict; so nothing to add + return stage; + } + } + } + // As we can add cwd without tree conflicts, we have to in order to + // ensure that installing this stage implies a directory at cwd. + std::unordered_map<std::string, ArtifactDescription> artifacts{}; + auto empty_tree = std::make_shared<Tree>(std::move(artifacts)); + auto empty_tree_id = empty_tree->Id(); + trees->emplace_back(std::move(empty_tree)); + auto empty_tree_exp = + ExpressionPtr{ArtifactDescription::CreateTree(empty_tree_id)}; + auto cwd_tree = ExpressionPtr{Expression::map_t{cwd, empty_tree_exp}}; + return ExpressionPtr{Expression::map_t{stage, cwd_tree}}; +} + auto BuildMaps::Target::Utils::getTainted( std::set<std::string>* tainted, const Configuration& config, |