refactor: add tr_sys_dir_get_files() (#5412)

This commit is contained in:
Charles Kerr
2023-04-18 16:23:20 -05:00
committed by GitHub
parent a8e01ac38d
commit f2aa3e197b
6 changed files with 65 additions and 103 deletions

View File

@@ -294,25 +294,12 @@ auto parseFile(std::string_view filename)
auto getFilenamesInDir(std::string_view folder)
{
auto files = std::vector<std::string>{};
if (auto const odir = tr_sys_dir_open(folder); odir != TR_BAD_SYS_DIR)
auto const prefix = std::string{ folder } + '/';
auto files = tr_sys_dir_get_files(folder);
for (auto& file : files)
{
char const* name = nullptr;
auto const prefix = std::string{ folder } + '/';
while ((name = tr_sys_dir_read_name(odir)) != nullptr)
{
if (name[0] == '.') // ignore dotfiles
{
continue;
}
files.emplace_back(prefix + name);
}
tr_sys_dir_close(odir);
file.insert(0, prefix);
}
return files;
}

View File

@@ -4,13 +4,16 @@
// License text can be found in the licenses/ folder.
#include <algorithm>
#include <string>
#include <string_view>
#include <vector>
#include "libtransmission/transmission.h"
#include "libtransmission/error.h"
#include "libtransmission/file.h"
#include "libtransmission/tr-assert.h"
#include "libtransmission/tr-strbuf.h"
using namespace std::literals;
@@ -33,3 +36,37 @@ bool tr_sys_file_write_line(tr_sys_file_t handle, std::string_view buffer, tr_er
return ret;
}
std::vector<std::string> tr_sys_dir_get_files(
std::string_view folder,
std::function<bool(std::string_view)> const& test,
tr_error** error)
{
if (auto const info = tr_sys_path_get_info(folder); !info || !info->isFolder())
{
return {};
}
auto const odir = tr_sys_dir_open(folder, error);
if (odir == TR_BAD_SYS_DIR)
{
return {};
}
auto filenames = std::vector<std::string>{};
for (;;)
{
char const* const name = tr_sys_dir_read_name(odir, error);
if (name == nullptr)
{
tr_sys_dir_close(odir, error);
return filenames;
}
if (test(name))
{
filenames.emplace_back(name);
}
}
}

View File

@@ -8,9 +8,11 @@
#include <cstddef> // size_t
#include <cstdint> // uint64_t
#include <ctime> // time_t
#include <functional>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
#ifdef _WIN32
#include <windows.h>
@@ -612,5 +614,15 @@ char const* tr_sys_dir_read_name(tr_sys_dir_t handle, struct tr_error** error =
*/
bool tr_sys_dir_close(tr_sys_dir_t handle, struct tr_error** error = nullptr);
[[nodiscard]] constexpr bool tr_basename_is_not_dotfile(std::string_view sv)
{
return std::empty(sv) || sv.front() != '.';
}
[[nodiscard]] std::vector<std::string> tr_sys_dir_get_files(
std::string_view folder,
std::function<bool(std::string_view name)> const& test = tr_basename_is_not_dotfile,
tr_error** error = nullptr);
/** @} */
/** @} */

View File

@@ -86,33 +86,16 @@ void walkTree(std::string_view const top, std::string_view const subpath, std::s
switch (info->type)
{
case TR_SYS_PATH_IS_DIRECTORY:
if (tr_sys_dir_t odir = tr_sys_dir_open(path); odir != TR_BAD_SYS_DIR)
for (auto const& name : tr_sys_dir_get_files(path))
{
for (;;)
if (!std::empty(subpath))
{
char const* const name = tr_sys_dir_read_name(odir);
if (name == nullptr)
{
break;
}
if (name[0] == '.') // skip dotfiles
{
continue;
}
if (!std::empty(subpath))
{
walkTree(top, tr_pathbuf{ subpath, '/', name }, files);
}
else
{
walkTree(top, name, files);
}
walkTree(top, tr_pathbuf{ subpath, '/', name }, files);
}
else
{
walkTree(top, name, files);
}
tr_sys_dir_close(odir);
}
break;

View File

@@ -1336,45 +1336,12 @@ namespace
{
namespace load_torrents_helpers
{
[[nodiscard]] std::vector<std::string> get_matching_files(
std::string const& folder,
std::function<bool(std::string_view)> const& test)
{
if (auto const info = tr_sys_path_get_info(folder); !info || !info->isFolder())
{
return {};
}
auto const odir = tr_sys_dir_open(folder);
if (odir == TR_BAD_SYS_DIR)
{
return {};
}
auto filenames = std::vector<std::string>{};
for (;;)
{
char const* const name = tr_sys_dir_read_name(odir);
if (name == nullptr)
{
tr_sys_dir_close(odir);
return filenames;
}
if (test(name))
{
filenames.emplace_back(name);
}
}
}
void session_load_torrents(tr_session* session, tr_ctor* ctor, std::promise<size_t>* loaded_promise)
{
auto n_torrents = size_t{};
auto const& folder = session->torrentDir();
for (auto const& name : get_matching_files(folder, [](auto const& name) { return tr_strvEndsWith(name, ".torrent"sv); }))
for (auto const& name : tr_sys_dir_get_files(folder, [](auto name) { return tr_strvEndsWith(name, ".torrent"sv); }))
{
auto const path = tr_pathbuf{ folder, '/', name };
@@ -1385,7 +1352,7 @@ void session_load_torrents(tr_session* session, tr_ctor* ctor, std::promise<size
}
auto buf = std::vector<char>{};
for (auto const& name : get_matching_files(folder, [](auto const& name) { return tr_strvEndsWith(name, ".magnet"sv); }))
for (auto const& name : tr_sys_dir_get_files(folder, [](auto name) { return tr_strvEndsWith(name, ".magnet"sv); }))
{
auto const path = tr_pathbuf{ folder, '/', name };

View File

@@ -110,32 +110,10 @@ void BaseWatchdir::processFile(std::string_view basename)
void BaseWatchdir::scan()
{
tr_error* error = nullptr;
auto const dir = tr_sys_dir_open(dirname_, &error);
if (dir == TR_BAD_SYS_DIR)
for (auto const& file : tr_sys_dir_get_files(dirname_, tr_basename_is_not_dotfile, &error))
{
tr_logAddWarn(fmt::format(
_("Couldn't read '{path}': {error} ({error_code})"),
fmt::arg("path", dirname()),
fmt::arg("error", error->message),
fmt::arg("error_code", error->code)));
tr_error_free(error);
return;
}
for (;;)
{
char const* const name = tr_sys_dir_read_name(dir, &error);
if (name == nullptr)
{
break;
}
if ("."sv == name || ".."sv == name)
{
continue;
}
processFile(name);
processFile(file);
}
if (error != nullptr)
@@ -147,8 +125,6 @@ void BaseWatchdir::scan()
fmt::arg("error_code", error->code)));
tr_error_free(error);
}
tr_sys_dir_close(dir);
}
} // namespace impl