refactor: wrap std::filesystem::space calls (#8284)

Co-authored-by: Charles Kerr <charles@charleskerr.com>
This commit is contained in:
Yat Ho
2026-01-31 01:18:04 +08:00
committed by GitHub
parent c4283e0c8f
commit 3a8a4d9b86
4 changed files with 70 additions and 36 deletions

View File

@@ -53,10 +53,9 @@ bool FreeSpaceLabel::Impl::on_freespace_timer()
return false;
}
auto ec = std::error_code{};
auto const capacity = std::filesystem::space(tr_u8path(dir_), ec);
auto const text = !ec ?
fmt::format(fmt::runtime(_("{disk_space} free")), fmt::arg("disk_space", tr_strlsize(capacity.available))) :
auto const capacity = tr_sys_path_get_capacity(std::string_view{ dir_ });
auto const text = capacity ?
fmt::format(fmt::runtime(_("{disk_space} free")), fmt::arg("disk_space", tr_strlsize(capacity->available))) :
_("Error");
label_.set_markup(fmt::format("<i>{:s}</i>", text));

View File

@@ -11,7 +11,6 @@
#include "libtransmission/error.h"
#include "libtransmission/file.h"
#include "libtransmission/tr-assert.h"
std::string tr_sys_path_resolve(std::string_view path, tr_error* error)
{
@@ -65,3 +64,19 @@ std::vector<std::string> tr_sys_dir_get_files(
}
}
}
std::optional<std::filesystem::space_info> tr_sys_path_get_capacity(std::filesystem::path const& path, tr_error* error)
{
auto ec = std::error_code{};
auto space = std::filesystem::space(path, ec);
if (!ec)
{
return space;
}
if (error != nullptr)
{
error->set(ec.value(), ec.message());
}
return {};
}

View File

@@ -102,6 +102,28 @@ struct tr_sys_path_info
}
};
/**
* Temporary replacement of deprecated `std::filesystem::u8path()` while we migrate
* from char to char8_t strings.
*
* https://stackoverflow.com/a/57635139/11390656
* @{
*/
template<typename InputIt>
[[nodiscard]] std::filesystem::path tr_u8path(InputIt begin, InputIt end)
{
auto const view = std::ranges::subrange(begin, end) | std::views::transform([](char const c) -> char8_t { return c; });
return { view.begin(), view.end() };
}
[[nodiscard]] inline std::filesystem::path tr_u8path(std::string_view path)
{
return tr_u8path(path.begin(), path.end());
}
/// @}
/**
* @name Platform-specific wrapper functions
*
@@ -144,6 +166,23 @@ bool tr_sys_path_copy(std::string_view src_path, std::string_view dst_path, tr_e
int flags = 0,
tr_error* error = nullptr);
/**
* @brief Get disk capacity and free disk space (in bytes) for the specified folder.
*
* @param[in] path Path to directory.
* @param[out] error Pointer to error object. Optional, pass `nullptr` if you
* are not interested in error details.
*/
[[nodiscard]] std::optional<std::filesystem::space_info> tr_sys_path_get_capacity(
std::filesystem::path const& path,
tr_error* error = nullptr);
[[nodiscard]] inline std::optional<std::filesystem::space_info> tr_sys_path_get_capacity(
std::string_view path,
tr_error* error = nullptr)
{
return tr_sys_path_get_capacity(tr_u8path(path), error);
}
/**
* @brief Portability wrapper for `access()`.
*
@@ -510,25 +549,3 @@ bool tr_sys_dir_close(tr_sys_dir_t handle, tr_error* error = nullptr);
/** @} */
/** @} */
/**
* Temporary replacement of deprecated `std::filesystem::u8path()` while we migrate
* from char to char8_t strings.
*
* https://stackoverflow.com/a/57635139/11390656
* @{
*/
template<typename InputIt>
[[nodiscard]] std::filesystem::path tr_u8path(InputIt begin, InputIt end)
{
auto const view = std::ranges::subrange(begin, end) | std::views::transform([](char const c) -> char8_t { return c; });
return { view.begin(), view.end() };
}
[[nodiscard]] inline std::filesystem::path tr_u8path(std::string_view path)
{
return tr_u8path(path.begin(), path.end());
}
/// @}

View File

@@ -2231,9 +2231,12 @@ using SessionAccessors = std::pair<SessionGetter, SessionSetter>;
TR_KEY_download_dir_free_space,
[](tr_session const& src) -> tr_variant
{
auto ec = std::error_code{};
auto const space = std::filesystem::space(tr_u8path(src.downloadDir()), ec);
return !ec ? space.available : tr_variant{ -1 };
// TODO(C++23): use std::optional::transform() instead
if (auto const space = tr_sys_path_get_capacity(std::string_view{ src.downloadDir() }))
{
return space->available;
}
return -1;
},
nullptr);
@@ -2736,17 +2739,17 @@ using SessionAccessors = std::pair<SessionGetter, SessionSetter>;
}
// get the free space
auto ec = std::error_code{};
auto const capacity = std::filesystem::space(tr_u8path(*path), ec);
auto error = tr_error{};
auto const capacity = tr_sys_path_get_capacity(*path, &error);
// response
args_out.try_emplace(TR_KEY_path, *path);
args_out.try_emplace(TR_KEY_size_bytes, !ec ? capacity.available : tr_variant{ -1 });
args_out.try_emplace(TR_KEY_total_size, !ec ? capacity.capacity : tr_variant{ -1 });
args_out.try_emplace(TR_KEY_size_bytes, capacity ? capacity->available : tr_variant{ -1 });
args_out.try_emplace(TR_KEY_total_size, capacity ? capacity->capacity : tr_variant{ -1 });
if (ec)
if (error)
{
return { Error::SYSTEM_ERROR, ec.message() };
return { Error::SYSTEM_ERROR, std::string{ error.message() } };
}
return { Error::SUCCESS, {} };
}