diff options
author | Paul Cristian Sarbu <paul.cristian.sarbu@huawei.com> | 2023-07-03 14:37:22 +0200 |
---|---|---|
committer | Paul Cristian Sarbu <paul.cristian.sarbu@huawei.com> | 2023-07-10 13:49:02 +0200 |
commit | 14715e3da452dd73363bc86f92cd9e5b9fdb3a7b (patch) | |
tree | 89c171c87e00d6f4163a7f707488d416941338ae /src | |
parent | 3bfe1cbe0dd1f61de37b61f33755d71a0b53db57 (diff) | |
download | justbuild-14715e3da452dd73363bc86f92cd9e5b9fdb3a7b.tar.gz |
FileSystemManager: Add recursive directory entries reader...
...allowing the skipping of certain subtrees if needed. This is
useful, e.g., in simulating what a 'git add' call would do,
which ignores all '.git' subdirectories.
Also adds a corresponding test for the new method.
Diffstat (limited to 'src')
-rw-r--r-- | src/buildtool/file_system/file_system_manager.hpp | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/src/buildtool/file_system/file_system_manager.hpp b/src/buildtool/file_system/file_system_manager.hpp index 5d86a4ff..868acbcc 100644 --- a/src/buildtool/file_system/file_system_manager.hpp +++ b/src/buildtool/file_system/file_system_manager.hpp @@ -23,6 +23,7 @@ #include <filesystem> #include <fstream> #include <optional> +#include <unordered_set> #include <fcntl.h> @@ -56,6 +57,9 @@ class FileSystemManager { using ReadDirEntryFunc = std::function<bool(std::filesystem::path const&, ObjectType type)>; + using UseDirEntryFunc = + std::function<bool(std::filesystem::path const&, bool /*is_tree*/)>; + class DirectoryAnchor { friend class FileSystemManager; @@ -724,6 +728,43 @@ class FileSystemManager { return true; } + /// \brief Read all entries recursively in a filesystem directory tree. + /// \param dir root directory to traverse + /// \param use_entry callback to call with found valid entries + /// \param ignored_subdirs directory names to be ignored wherever found in + /// the directory tree of dir. + [[nodiscard]] static auto ReadDirectoryEntriesRecursive( + std::filesystem::path const& dir, + UseDirEntryFunc const& use_entry, + std::unordered_set<std::string> const& ignored_subdirs = {}) noexcept + -> bool { + try { + // constructor of this iterator points to end by default; + for (auto it = std::filesystem::recursive_directory_iterator(dir); + it != std::filesystem::recursive_directory_iterator(); + ++it) { + // check for ignored subdirs + if (std::filesystem::is_directory(it->symlink_status()) and + ignored_subdirs.contains(*--it->path().end())) { + it.disable_recursion_pending(); + continue; + } + // use the entry + if (not use_entry( + it->path().lexically_relative(dir), + std::filesystem::is_directory(it->symlink_status()))) { + return false; + } + } + } catch (std::exception const& ex) { + Logger::Log(LogLevel::Error, + "reading directory {} recursively failed", + dir.string()); + return false; + } + return true; + } + /// \brief Read the content of a symlink. [[nodiscard]] static auto ReadSymlink(std::filesystem::path const& link) -> std::optional<std::string> { |