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:
parent
acee39e15c
commit
2c2011d40f
4 changed files with 52 additions and 24 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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{};
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
Loading…
Add table
Reference in a new issue