Skip to content

Commit

Permalink
Files::get_regular_files_recursive_proximate (#337)
Browse files Browse the repository at this point in the history
* Files::get_regular_files_recursive_proximate

* Address CR comments

* Rename to get_regular_files_recursive_lexically_proximate

* Remove PushPopElement
  • Loading branch information
ras0219-msft authored Jan 31, 2022
1 parent f95f306 commit f82ce3f
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 12 deletions.
4 changes: 4 additions & 0 deletions include/vcpkg/base/files.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,10 @@ namespace vcpkg
virtual std::vector<Path> get_regular_files_recursive(const Path& dir, std::error_code& ec) const = 0;
std::vector<Path> get_regular_files_recursive(const Path& dir, LineInfo li) const;

virtual std::vector<Path> get_regular_files_recursive_lexically_proximate(const Path& dir,
std::error_code& ec) const = 0;
std::vector<Path> get_regular_files_recursive_lexically_proximate(const Path& dir, LineInfo li) const;

virtual std::vector<Path> get_regular_files_non_recursive(const Path& dir, std::error_code& ec) const = 0;
std::vector<Path> get_regular_files_non_recursive(const Path& dir, LineInfo li) const;

Expand Down
21 changes: 21 additions & 0 deletions src/vcpkg-test/files.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ namespace
template<class Enumerator, class ExpectedGenerator>
void do_filesystem_enumeration_test(Enumerator&& enumerator, ExpectedGenerator&& generate_expected)
{
// Note: not seeded with random data, so this will always produce the same sequence of names
urbg_t urbg;

auto& fs = setup();
Expand All @@ -186,6 +187,8 @@ namespace
const auto target_inside_directory = target_directory / "some-inner-directory";
const auto target_inside_directory_symlink = target_directory / "symlink-to-some-inner-directory";

fs.remove_all(temp_dir, VCPKG_LINE_INFO);

fs.create_directory(temp_dir, VCPKG_LINE_INFO);
fs.create_directory(target_root, VCPKG_LINE_INFO);
fs.create_directory(target_directory, VCPKG_LINE_INFO);
Expand All @@ -198,6 +201,7 @@ namespace
fs.create_symlink(target_file, target_symlink, ec);
if (ec)
{
INFO(ec.message());
REQUIRE(is_valid_symlink_failure(ec));
}
else
Expand Down Expand Up @@ -741,6 +745,23 @@ TEST_CASE ("get_files_recursive_symlinks", "[files]")
});
}

TEST_CASE ("get_regular_files_recursive_proximate_symlinks", "[files]")
{
do_filesystem_enumeration_test(
[](Filesystem& fs, const Path& root) {
return fs.get_regular_files_recursive_lexically_proximate(root, VCPKG_LINE_INFO);
},
[](const Path&) {
Path somedir{"some-directory"};
return std::vector<Path>{
"file.txt",
somedir / "file2.txt",
somedir / "symlink-to-file2.txt",
"symlink-to-file.txt",
};
});
}

TEST_CASE ("get_files_non_recursive_symlinks", "[files]")
{
do_filesystem_enumeration_test(
Expand Down
65 changes: 53 additions & 12 deletions src/vcpkg/base/files.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -826,7 +826,7 @@ namespace
{
// if it isn't still a directory something is racy
ec = std::make_error_code(std::errc::device_or_resource_busy);
mark_recursive_error(base, ec, failure_point);
failure_point = base;
return;
}

Expand Down Expand Up @@ -1420,6 +1420,18 @@ namespace vcpkg
return maybe_directories;
}

std::vector<Path> Filesystem::get_regular_files_recursive_lexically_proximate(const Path& dir, LineInfo li) const
{
std::error_code ec;
auto maybe_directories = this->get_regular_files_recursive_lexically_proximate(dir, ec);
if (ec)
{
exit_filesystem_call_error(li, ec, __func__, {dir});
}

return maybe_directories;
}

std::vector<Path> Filesystem::get_regular_files_non_recursive(const Path& dir, LineInfo li) const
{
std::error_code ec;
Expand Down Expand Up @@ -2066,6 +2078,21 @@ namespace vcpkg
{
return get_regular_files_impl<stdfs::directory_iterator>(dir, ec);
}

virtual std::vector<Path> get_regular_files_recursive_lexically_proximate(const Path& dir,
std::error_code& ec) const override
{
auto ret = this->get_regular_files_recursive(dir, ec);
if (!ec)
{
const auto base = to_stdfs_path(dir);
for (auto& p : ret)
{
p = from_stdfs_path(to_stdfs_path(p).lexically_proximate(base));
}
}
return ret;
}
#else // ^^^ _WIN32 // !_WIN32 vvv
static void insert_if_stat_matches(std::vector<Path>& result,
const Path& full,
Expand Down Expand Up @@ -2101,6 +2128,7 @@ namespace vcpkg

static void get_files_recursive_impl(std::vector<Path>& result,
const Path& base,
const Path& out_base,
std::error_code& ec,
bool want_directories,
bool want_regular_files,
Expand Down Expand Up @@ -2135,6 +2163,7 @@ namespace vcpkg
}

const auto full = base / entry->d_name;
const auto out_full = out_base / entry->d_name;
const auto entry_dtype = get_d_type(entry);
struct stat s;
struct stat ls;
Expand All @@ -2144,11 +2173,11 @@ namespace vcpkg
if (want_directories)
{
// push results before recursion to get outer entries first
result.push_back(full);
result.push_back(out_full);
}

get_files_recursive_impl(
result, full, ec, want_directories, want_regular_files, want_other);
result, full, out_full, ec, want_directories, want_regular_files, want_other);
if (ec)
{
return;
Expand All @@ -2158,7 +2187,7 @@ namespace vcpkg
case PosixDType::Regular:
if (want_regular_files)
{
result.push_back(full);
result.push_back(out_full);
}

break;
Expand All @@ -2169,7 +2198,7 @@ namespace vcpkg
case PosixDType::BlockDevice:
if (want_other)
{
result.push_back(full);
result.push_back(out_full);
}

break;
Expand All @@ -2196,7 +2225,7 @@ namespace vcpkg
if (want_directories && want_regular_files && want_other)
{
// skip extra stat syscall since we want everything
result.push_back(full);
result.push_back(out_full);
}
else
{
Expand All @@ -2216,21 +2245,21 @@ namespace vcpkg
}

insert_if_stat_matches(
result, full, &s, want_directories, want_regular_files, want_other);
result, out_full, &s, want_directories, want_regular_files, want_other);
}
}
else
{
// push results before recursion to get outer entries first
insert_if_stat_matches(
result, full, &ls, want_directories, want_regular_files, want_other);
result, out_full, &ls, want_directories, want_regular_files, want_other);
}

// recursion check doesn't follow symlinks:
if (S_ISDIR(ls.st_mode))
{
get_files_recursive_impl(
result, full, ec, want_directories, want_regular_files, want_other);
result, full, out_full, ec, want_directories, want_regular_files, want_other);
}
break;
}
Expand Down Expand Up @@ -2286,7 +2315,8 @@ namespace vcpkg
virtual std::vector<Path> get_files_recursive(const Path& dir, std::error_code& ec) const override
{
std::vector<Path> result;
get_files_recursive_impl(result, dir, ec, true, true, true);
Path out_base = dir;
get_files_recursive_impl(result, dir, out_base, ec, true, true, true);
return result;
}

Expand All @@ -2300,7 +2330,8 @@ namespace vcpkg
virtual std::vector<Path> get_directories_recursive(const Path& dir, std::error_code& ec) const override
{
std::vector<Path> result;
get_files_recursive_impl(result, dir, ec, true, false, false);
Path out_base = dir;
get_files_recursive_impl(result, dir, out_base, ec, true, false, false);

return result;
}
Expand Down Expand Up @@ -2329,7 +2360,17 @@ namespace vcpkg
virtual std::vector<Path> get_regular_files_recursive(const Path& dir, std::error_code& ec) const override
{
std::vector<Path> result;
get_files_recursive_impl(result, dir, ec, false, true, false);
Path out_base = dir;
get_files_recursive_impl(result, dir, out_base, ec, false, true, false);
return result;
}

virtual std::vector<Path> get_regular_files_recursive_lexically_proximate(const Path& dir,
std::error_code& ec) const override
{
std::vector<Path> result;
Path out_base;
get_files_recursive_impl(result, dir, out_base, ec, false, true, false);
return result;
}

Expand Down

0 comments on commit f82ce3f

Please sign in to comment.