mirror of
https://github.com/NixOS/nix
synced 2025-06-25 10:41:16 +02:00
add DirectoryIterator to re-throw std::filesystem::filesystem_error
Co-authored-by: Sergei Zimmerman <145775305+xokdvium@users.noreply.github.com>
(cherry picked from commit 7ccc0d591f
)
This commit is contained in:
parent
8de4c272dc
commit
0f4b17e51f
3 changed files with 126 additions and 0 deletions
|
@ -275,4 +275,26 @@ TEST(makeParentCanonical, root)
|
||||||
{
|
{
|
||||||
ASSERT_EQ(makeParentCanonical("/"), "/");
|
ASSERT_EQ(makeParentCanonical("/"), "/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* DirectoryIterator
|
||||||
|
* --------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
TEST(DirectoryIterator, works)
|
||||||
|
{
|
||||||
|
auto tmpDir = nix::createTempDir();
|
||||||
|
nix::AutoDelete delTmpDir(tmpDir, true);
|
||||||
|
|
||||||
|
nix::writeFile(tmpDir + "/somefile", "");
|
||||||
|
|
||||||
|
for (auto path : DirectoryIterator(tmpDir)) {
|
||||||
|
ASSERT_EQ(path.path().string(), tmpDir + "/somefile");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(DirectoryIterator, nonexistent)
|
||||||
|
{
|
||||||
|
ASSERT_THROW(DirectoryIterator("/schnitzel/darmstadt/pommes"), SysError);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,34 @@ namespace fs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DirectoryIterator::DirectoryIterator(const std::filesystem::path& p) {
|
||||||
|
try {
|
||||||
|
// **Attempt to create the underlying directory_iterator**
|
||||||
|
it_ = std::filesystem::directory_iterator(p);
|
||||||
|
} catch (const std::filesystem::filesystem_error& e) {
|
||||||
|
// **Catch filesystem_error and throw SysError**
|
||||||
|
// Adapt the error message as needed for SysError
|
||||||
|
throw SysError("cannot read directory %s", p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DirectoryIterator& DirectoryIterator::operator++() {
|
||||||
|
// **Attempt to increment the underlying iterator**
|
||||||
|
std::error_code ec;
|
||||||
|
it_.increment(ec);
|
||||||
|
if (ec) {
|
||||||
|
// Try to get path info if possible, might fail if iterator is bad
|
||||||
|
try {
|
||||||
|
if (it_ != std::filesystem::directory_iterator{}) {
|
||||||
|
throw SysError("cannot read directory past %s: %s", it_->path(), ec.message());
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
throw SysError("cannot read directory");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
bool isAbsolute(PathView path)
|
bool isAbsolute(PathView path)
|
||||||
{
|
{
|
||||||
return fs::path { path }.is_absolute();
|
return fs::path { path }.is_absolute();
|
||||||
|
|
|
@ -360,4 +360,80 @@ typedef std::function<bool(const Path & path)> PathFilter;
|
||||||
|
|
||||||
extern PathFilter defaultPathFilter;
|
extern PathFilter defaultPathFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change permissions of a file only if necessary.
|
||||||
|
*
|
||||||
|
* @details
|
||||||
|
* Skip chmod call if the directory already has the requested permissions.
|
||||||
|
* This is to avoid failing when the executing user lacks permissions to change the
|
||||||
|
* directory's permissions even if it would be no-op.
|
||||||
|
*
|
||||||
|
* @param path Path to the file to change the permissions for.
|
||||||
|
* @param mode New file mode.
|
||||||
|
* @param mask Used for checking if the file already has requested permissions.
|
||||||
|
*
|
||||||
|
* @return true if permissions changed, false otherwise.
|
||||||
|
*/
|
||||||
|
bool chmodIfNeeded(const std::filesystem::path & path, mode_t mode, mode_t mask = S_IRWXU | S_IRWXG | S_IRWXO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A directory iterator that can be used to iterate over the
|
||||||
|
* contents of a directory. It is similar to std::filesystem::directory_iterator
|
||||||
|
* but throws NixError on failure instead of std::filesystem::filesystem_error.
|
||||||
|
*/
|
||||||
|
class DirectoryIterator {
|
||||||
|
public:
|
||||||
|
// --- Iterator Traits ---
|
||||||
|
using iterator_category = std::input_iterator_tag;
|
||||||
|
using value_type = std::filesystem::directory_entry;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using pointer = const std::filesystem::directory_entry*;
|
||||||
|
using reference = const std::filesystem::directory_entry&;
|
||||||
|
|
||||||
|
// Default constructor (represents end iterator)
|
||||||
|
DirectoryIterator() noexcept = default;
|
||||||
|
|
||||||
|
// Constructor taking a path
|
||||||
|
explicit DirectoryIterator(const std::filesystem::path& p);
|
||||||
|
|
||||||
|
reference operator*() const {
|
||||||
|
// Accessing the value itself doesn't typically throw filesystem_error
|
||||||
|
// after successful construction/increment, but underlying operations might.
|
||||||
|
// If directory_entry methods called via -> could throw, add try-catch there.
|
||||||
|
return *it_;
|
||||||
|
}
|
||||||
|
|
||||||
|
pointer operator->() const {
|
||||||
|
return &(*it_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DirectoryIterator& operator++();
|
||||||
|
|
||||||
|
// Postfix increment operator
|
||||||
|
DirectoryIterator operator++(int) {
|
||||||
|
DirectoryIterator temp = *this;
|
||||||
|
++(*this); // Uses the prefix increment's try-catch logic
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equality comparison
|
||||||
|
friend bool operator==(const DirectoryIterator& a, const DirectoryIterator& b) noexcept {
|
||||||
|
return a.it_ == b.it_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inequality comparison
|
||||||
|
friend bool operator!=(const DirectoryIterator& a, const DirectoryIterator& b) noexcept {
|
||||||
|
return !(a == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow direct use in range-based for loops if iterating over an instance
|
||||||
|
DirectoryIterator begin() const { return *this; }
|
||||||
|
DirectoryIterator end() const { return DirectoryIterator{}; }
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::filesystem::directory_iterator it_;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue