1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2025-03-11 06:32:59 +00:00

fix: update partial file suffix after verifying torrent (#6871)

* fix: only update piece completion if different

* fix: remove return statement from void function

* refactor: add `tr_torrent::has_file()`

* fix: update file suffixes after verifying torrent

* fix: tests
This commit is contained in:
Yat Ho 2024-06-02 08:44:01 +08:00 committed by GitHub
parent acee39e15c
commit 2c2011d40f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 52 additions and 24 deletions

View file

@ -1608,6 +1608,39 @@ std::optional<std::string> tr_torrent::VerifyMediator::find_file(tr_file_index_t
return {};
}
void tr_torrent::update_file_path(tr_file_index_t file, std::optional<bool> has_file) const
{
auto const found = find_file(file);
if (!found)
{
return;
}
auto const has = has_file ? *has_file : this->has_file(file);
auto const needs_suffix = session->isIncompleteFileNamingEnabled() && !has;
auto const oldpath = found->filename();
auto const newpath = needs_suffix ?
tr_pathbuf{ found->base(), '/', file_subpath(file), tr_torrent_files::PartialFileSuffix } :
tr_pathbuf{ found->base(), '/', file_subpath(file) };
if (tr_sys_path_is_same(oldpath, newpath))
{
return;
}
if (auto error = tr_error{}; !tr_sys_path_rename(oldpath, newpath, &error))
{
tr_logAddErrorTor(
this,
fmt::format(
_("Couldn't move '{old_path}' to '{path}': {error} ({error_code})"),
fmt::arg("old_path", oldpath),
fmt::arg("path", newpath),
fmt::arg("error", error.message()),
fmt::arg("error_code", error.code())));
}
}
void tr_torrent::VerifyMediator::on_verify_queued()
{
tr_logAddTraceTor(tor_, "Queued for verification");
@ -1625,7 +1658,7 @@ void tr_torrent::VerifyMediator::on_piece_checked(tr_piece_index_t const piece,
{
auto const had_piece = tor_->has_piece(piece);
if (has_piece || had_piece)
if (has_piece != had_piece)
{
tor_->set_has_piece(piece, has_piece);
tor_->set_dirty();
@ -1664,6 +1697,11 @@ void tr_torrent::VerifyMediator::on_verify_done(bool const aborted)
return;
}
for (tr_file_index_t file = 0, n_files = tor->file_count(); file < n_files; ++file)
{
tor->update_file_path(file, {});
}
tor->recheck_completeness();
if (tor->verify_done_callback_)
@ -2132,27 +2170,7 @@ void tr_torrent::on_file_completed(tr_file_index_t const file)
/* if the torrent's current filename isn't the same as the one in the
* metadata -- for example, if it had the ".part" suffix appended to
* it until now -- then rename it to match the one in the metadata */
if (auto found = find_file(file); found)
{
if (auto const& file_subpath = this->file_subpath(file); file_subpath != found->subpath())
{
auto const& oldpath = found->filename();
auto const newpath = tr_pathbuf{ found->base(), '/', file_subpath };
auto error = tr_error{};
if (!tr_sys_path_rename(oldpath, newpath, &error))
{
tr_logAddErrorTor(
this,
fmt::format(
_("Couldn't move '{old_path}' to '{path}': {error} ({error_code})"),
fmt::arg("old_path", oldpath),
fmt::arg("path", newpath),
fmt::arg("error", error.message()),
fmt::arg("error_code", error.code())));
}
}
}
update_file_path(file, true);
}
void tr_torrent::on_piece_completed(tr_piece_index_t const piece)
@ -2165,7 +2183,7 @@ void tr_torrent::on_piece_completed(tr_piece_index_t const piece)
// if this piece completes any file, invoke the fileCompleted func for it
for (auto [file, file_end] = fpm_.file_span_for_piece(piece); file < file_end; ++file)
{
if (completion_.has_blocks(block_span_for_file(file)))
if (has_file(file))
{
on_file_completed(file);
}

View file

@ -325,6 +325,11 @@ struct tr_torrent
return completion_.has_none();
}
[[nodiscard]] auto has_file(tr_file_index_t file) const
{
return completion_.has_blocks(block_span_for_file(file));
}
[[nodiscard]] auto has_piece(tr_piece_index_t piece) const
{
return completion_.has_piece(piece);
@ -372,7 +377,7 @@ struct tr_torrent
void amount_done_bins(float* tab, int n_tabs) const
{
return completion_.amount_done(tab, n_tabs);
completion_.amount_done(tab, n_tabs);
}
/// FILE <-> PIECE
@ -1249,6 +1254,8 @@ private:
void do_magnet_idle_work();
[[nodiscard]] bool use_new_metainfo(tr_error* error);
void update_file_path(tr_file_index_t file, std::optional<bool> has_file) const;
void set_location_in_session_thread(std::string_view path, bool move_from_old_path, int volatile* setme_state);
void rename_path_in_session_thread(

View file

@ -56,6 +56,7 @@ TEST_P(IncompleteDirTest, incompleteDir)
// init an incomplete torrent.
// the test zero_torrent will be missing its first piece.
tr_sessionSetIncompleteFileNamingEnabled(session_, true);
auto* const tor = zeroTorrentInit(ZeroTorrentState::Partial);
auto path = tr_pathbuf{};

View file

@ -449,6 +449,8 @@ TEST_F(RenameTest, partialFile)
**** create our test torrent with an incomplete .part file
***/
tr_sessionSetIncompleteFileNamingEnabled(session_, true);
auto* tor = zeroTorrentInit(ZeroTorrentState::Partial);
EXPECT_EQ(TotalSize, tor->total_size());
EXPECT_EQ(PieceSize, tor->piece_size());