From db961e1e9fba6e0c439f69ac8342ef887d9d19a6 Mon Sep 17 00:00:00 2001 From: Paul Cristian Sarbu Date: Tue, 20 Jun 2023 17:54:07 +0200 Subject: Add non-upwards symlinks in the rule language... via a 'SYMLINK' constructor function. This works similarly to the 'FILE' construct, but the name given must point to a non-upwards symlink and a symlink artifact is being generated from it. Also updates the relevant tests. --- .../build_engine/base_maps/entity_name.hpp | 13 +++++--- .../build_engine/base_maps/entity_name_data.hpp | 12 ++++++- .../build_engine/target_map/target_map.cpp | 37 ++++++++++++++++++++++ src/buildtool/main/main.cpp | 3 ++ 4 files changed, 59 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/buildtool/build_engine/base_maps/entity_name.hpp b/src/buildtool/build_engine/base_maps/entity_name.hpp index e2df632e..bec5b083 100644 --- a/src/buildtool/build_engine/base_maps/entity_name.hpp +++ b/src/buildtool/build_engine/base_maps/entity_name.hpp @@ -112,11 +112,13 @@ template std::nullopt) noexcept -> std::optional { try { bool const is_file = s0 == EntityName::kFileLocationMarker; + bool const is_glob = s0 == EntityName::kGlobMarker; + bool const is_symlink = s0 == EntityName::kSymlinkLocationMarker; auto const ref_type = - s0 == EntityName::kFileLocationMarker - ? ReferenceType::kFile - : (s0 == EntityName::kGlobMarker ? ReferenceType::kGlob - : ReferenceType::kTree); + is_file ? ReferenceType::kFile + : (is_glob ? ReferenceType::kGlob + : (is_symlink ? ReferenceType::kSymlink + : ReferenceType::kTree)); if (list_size == 3) { if (IsString(list[2])) { auto const& name = GetString(list[2]); @@ -232,7 +234,8 @@ template } else if (s0 == EntityName::kFileLocationMarker or s0 == EntityName::kTreeLocationMarker or - s0 == EntityName::kGlobMarker) { + s0 == EntityName::kGlobMarker or + s0 == EntityName::kSymlinkLocationMarker) { return ParseEntityNameFSReference( s0, list, list_size, current, logger); } diff --git a/src/buildtool/build_engine/base_maps/entity_name_data.hpp b/src/buildtool/build_engine/base_maps/entity_name_data.hpp index c44be2b3..0de1b48f 100644 --- a/src/buildtool/build_engine/base_maps/entity_name_data.hpp +++ b/src/buildtool/build_engine/base_maps/entity_name_data.hpp @@ -38,7 +38,13 @@ struct AnonymousTarget { } }; -enum class ReferenceType : std::int8_t { kTarget, kFile, kTree, kGlob }; +enum class ReferenceType : std::int8_t { + kTarget, + kFile, + kTree, + kGlob, + kSymlink +}; struct NamedTarget { std::string repository{}; @@ -80,6 +86,7 @@ class EntityName { static constexpr auto kFileLocationMarker = "FILE"; static constexpr auto kTreeLocationMarker = "TREE"; static constexpr auto kGlobMarker = "GLOB"; + static constexpr auto kSymlinkLocationMarker = "SYMLINK"; static constexpr auto kRelativeLocationMarker = "./"; static constexpr auto kAnonymousMarker = "#"; @@ -137,6 +144,9 @@ class EntityName { else if (x.reference_t == ReferenceType::kGlob) { j.push_back(kGlobMarker); } + else if (x.reference_t == ReferenceType::kSymlink) { + j.push_back(kSymlinkLocationMarker); + } j.push_back(x.module); j.push_back(x.name); } diff --git a/src/buildtool/build_engine/target_map/target_map.cpp b/src/buildtool/build_engine/target_map/target_map.cpp index d2e73f07..99f6d9f0 100644 --- a/src/buildtool/build_engine/target_map/target_map.cpp +++ b/src/buildtool/build_engine/target_map/target_map.cpp @@ -1471,6 +1471,17 @@ void TreeTarget( .config = Configuration{}}); } + for (const auto& x : dir_entries.SymlinksIterator()) { + v.emplace_back(ConfiguredTarget{ + .target = + BuildMaps::Base::EntityName{ + target.repository, + dir_name, + x, + BuildMaps::Base::ReferenceType::kSymlink}, + .config = Configuration{}}); + } + for (const auto& x : dir_entries.DirectoriesIterator()) { v.emplace_back(ConfiguredTarget{ .target = @@ -1573,6 +1584,15 @@ void GlobTargetWithDirEntry( BuildMaps::Base::ReferenceType::kFile}); } } + for (auto const& x : dir.SymlinksIterator()) { + if (fnmatch(pattern.c_str(), x.c_str(), 0) == 0) { + matches.emplace_back(BuildMaps::Base::EntityName{ + target.repository, + target.module, + x, + BuildMaps::Base::ReferenceType::kSymlink}); + } + } source_target_map->ConsumeAfterKeysReady( ts, matches, @@ -1644,6 +1664,23 @@ auto CreateTargetMap( fatal); }); } + else if (key.target.GetNamedTarget().reference_t == + BuildMaps::Base::ReferenceType::kSymlink) { + // Not a defined target, treat as source target + source_target_map->ConsumeAfterKeysReady( + ts, + {key.target}, + [setter](auto values) { + (*setter)(AnalysedTargetPtr{*values[0]}); + }, + [logger, target = key.target](auto const& msg, auto fatal) { + (*logger)(fmt::format("While analysing target {} as " + "symlink:\n{}", + target.ToString(), + msg), + fatal); + }); + } else if (key.target.GetNamedTarget().reference_t == BuildMaps::Base::ReferenceType::kGlob) { auto wrapped_logger = std::make_shared( diff --git a/src/buildtool/main/main.cpp b/src/buildtool/main/main.cpp index 288101f5..5589b0e0 100644 --- a/src/buildtool/main/main.cpp +++ b/src/buildtool/main/main.cpp @@ -1238,6 +1238,9 @@ auto DetermineNonExplicitTarget( case Base::ReferenceType::kGlob: std::cout << id.ToString() << " is a glob." << std::endl; return std::nullopt; + case Base::ReferenceType::kSymlink: + std::cout << id.ToString() << " is a symlink." << std::endl; + return std::nullopt; case Base::ReferenceType::kTarget: return id; } -- cgit v1.2.3