public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/transmission] epel10: 4.0.1
@ 2026-07-20 20:37 Gwyn Ciesla
  0 siblings, 0 replies; only message in thread
From: Gwyn Ciesla @ 2026-07-20 20:37 UTC (permalink / raw)
  To: git-commits

A new commit has been pushed.

Repo   : rpms/transmission
Branch : epel10
Commit : fd2294bdc8759b753ad4eff7d233a4b0e2b0ab63
Author : Gwyn Ciesla <gwync@protonmail.com>
Date   : 2023-02-23T10:19:31-06:00
Stats  : +8/-869 in 5 file(s)
URL    : https://src.fedoraproject.org/rpms/transmission/c/fd2294bdc8759b753ad4eff7d233a4b0e2b0ab63?branch=epel10

Log:
4.0.1

---
diff --git a/.gitignore b/.gitignore
index 75a6f39..0327bd0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,3 +27,4 @@ transmission-2.04.tar.xz
 /transmission-2.94.tar.xz
 /transmission-3.00.tar.xz
 /transmission-4.0.0.tar.xz
+/transmission-4.0.1.tar.xz

diff --git a/4890.patch b/4890.patch
deleted file mode 100644
index 2941f42..0000000
--- a/4890.patch
+++ /dev/null
@@ -1,363 +0,0 @@
-From ba97fb792c248320edd6353593feaff91b1155ef Mon Sep 17 00:00:00 2001
-From: Charles Kerr <charles@charleskerr.com>
-Date: Tue, 14 Feb 2023 10:30:54 -0600
-Subject: [PATCH 1/3] fix: processing of block fragments that arrive
- out-of-order from request
-
-Fixes 4.0.0 regression on torrents whose pieces did not align on block boundaries.
----
- libtransmission/cache.cc     |  2 +-
- libtransmission/cache.h      |  2 +-
- libtransmission/peer-msgs.cc | 96 ++++++++++++++++++------------------
- libtransmission/torrent.cc   | 11 ++++-
- libtransmission/webseed.cc   |  2 +-
- 5 files changed, 60 insertions(+), 53 deletions(-)
-
-diff --git a/libtransmission/cache.cc b/libtransmission/cache.cc
-index ef446b244c..f7ae03dcc1 100644
---- a/libtransmission/cache.cc
-+++ b/libtransmission/cache.cc
-@@ -140,7 +140,7 @@ Cache::Cache(tr_torrents& torrents, int64_t max_bytes)
- 
- // ---
- 
--int Cache::writeBlock(tr_torrent_id_t tor_id, tr_block_index_t block, std::unique_ptr<std::vector<uint8_t>>& writeme)
-+int Cache::writeBlock(tr_torrent_id_t tor_id, tr_block_index_t block, std::unique_ptr<std::vector<uint8_t>> writeme)
- {
-     auto const key = Key{ tor_id, block };
-     auto iter = std::lower_bound(std::begin(blocks_), std::end(blocks_), key, CompareCacheBlockByKey{});
-diff --git a/libtransmission/cache.h b/libtransmission/cache.h
-index e25deb2328..9d6455610b 100644
---- a/libtransmission/cache.h
-+++ b/libtransmission/cache.h
-@@ -36,7 +36,7 @@ class Cache
-     }
- 
-     // @return any error code from cacheTrim()
--    int writeBlock(tr_torrent_id_t tor, tr_block_index_t block, std::unique_ptr<std::vector<uint8_t>>& writeme);
-+    int writeBlock(tr_torrent_id_t tor, tr_block_index_t block, std::unique_ptr<std::vector<uint8_t>> writeme);
- 
-     int readBlock(tr_torrent* torrent, tr_block_info::Location loc, uint32_t len, uint8_t* setme);
-     int prefetchBlock(tr_torrent* torrent, tr_block_info::Location loc, uint32_t len);
-diff --git a/libtransmission/peer-msgs.cc b/libtransmission/peer-msgs.cc
-index 837dbb4b76..05864fea20 100644
---- a/libtransmission/peer-msgs.cc
-+++ b/libtransmission/peer-msgs.cc
-@@ -188,7 +188,20 @@ struct tr_incoming
-     uint8_t id = 0; // the protocol message, e.g. BtPeerMsgs::Piece
-     uint32_t length = 0; // the full message payload length. Includes the +1 for id length
-     std::optional<peer_request> block_req; // metadata for incoming blocks
--    std::map<tr_block_index_t, std::unique_ptr<std::vector<uint8_t>>> block_buf; // piece data for incoming blocks
-+
-+    struct incoming_piece_data
-+    {
-+        explicit incoming_piece_data(uint32_t block_size)
-+            : buf{ std::make_unique<std::vector<uint8_t>>(block_size) }
-+        {
-+        }
-+
-+        uint32_t n_bytes_received = 0;
-+
-+        std::unique_ptr<std::vector<uint8_t>> buf;
-+    };
-+
-+    std::map<tr_block_index_t, incoming_piece_data> blocks;
- };
- 
- class tr_peerMsgsImpl;
-@@ -1397,7 +1410,7 @@ bool messageLengthIsCorrect(tr_peerMsgsImpl const* msg, uint8_t id, uint32_t len
-     }
- }
- 
--int clientGotBlock(tr_peerMsgsImpl* msgs, std::unique_ptr<std::vector<uint8_t>>& block_data, tr_block_index_t block);
-+int clientGotBlock(tr_peerMsgsImpl* msgs, std::unique_ptr<std::vector<uint8_t>> block_data, tr_block_index_t block);
- 
- ReadState readBtPiece(tr_peerMsgsImpl* msgs, size_t inlen, size_t* setme_piece_bytes_read)
- {
-@@ -1406,7 +1419,8 @@ ReadState readBtPiece(tr_peerMsgsImpl* msgs, size_t inlen, size_t* setme_piece_b
-     logtrace(msgs, "In readBtPiece");
- 
-     // If this is the first we've seen of the piece data, parse out the header
--    if (!msgs->incoming.block_req)
-+    auto& incoming = msgs->incoming;
-+    if (!incoming.block_req)
-     {
-         if (inlen < 8)
-         {
-@@ -1416,67 +1430,55 @@ ReadState readBtPiece(tr_peerMsgsImpl* msgs, size_t inlen, size_t* setme_piece_b
-         auto req = peer_request{};
-         msgs->io->read_uint32(&req.index);
-         msgs->io->read_uint32(&req.offset);
--        req.length = msgs->incoming.length - 9;
-+        req.length = incoming.length - 9;
-         logtrace(msgs, fmt::format(FMT_STRING("got incoming block header {:d}:{:d}->{:d}"), req.index, req.offset, req.length));
--        msgs->incoming.block_req = req;
-+        incoming.block_req = req;
-         return READ_NOW;
-     }
- 
--    auto& req = msgs->incoming.block_req;
-+    auto& req = incoming.block_req;
-     auto const loc = msgs->torrent->pieceLoc(req->index, req->offset);
-     auto const block = loc.block;
-     auto const block_size = msgs->torrent->blockSize(block);
--    auto& block_buf = msgs->incoming.block_buf[block];
--    if (!block_buf)
--    {
--        block_buf = std::make_unique<std::vector<uint8_t>>();
--        block_buf->reserve(block_size);
--    }
- 
--    // read in another chunk of data
--    auto const n_left_in_block = block_size - std::size(*block_buf);
--    auto const n_left_in_req = size_t{ req->length };
--    auto const n_to_read = std::min({ n_left_in_block, n_left_in_req, inlen });
--    auto const old_length = std::size(*block_buf);
--    block_buf->resize(old_length + n_to_read);
--    msgs->io->read_bytes(&((*block_buf)[old_length]), n_to_read);
-+    auto const n_this_pass = std::min(size_t{ req->length }, inlen);
-+    TR_ASSERT(loc.block_offset + n_this_pass <= block_size);
- 
--    msgs->publish(tr_peer_event::GotPieceData(n_to_read));
--    *setme_piece_bytes_read += n_to_read;
--    logtrace(
--        msgs,
--        fmt::format(
--            FMT_STRING("got {:d} bytes for block {:d}:{:d}->{:d} ... {:d} remain in req, {:d} remain in block"),
--            n_to_read,
--            req->index,
--            req->offset,
--            req->length,
--            req->length,
--            block_size - std::size(*block_buf)));
--
--    // if we didn't read enough to finish off the request,
--    // update the table and wait for more
--    if (n_to_read < n_left_in_req)
--    {
--        auto new_loc = msgs->torrent->byteLoc(loc.byte + n_to_read);
-+    auto& incoming_block = incoming.blocks.try_emplace(block, block_size).first->second;
-+    msgs->io->read_bytes(std::data(*incoming_block.buf) + loc.block_offset, n_this_pass);
-+
-+    msgs->publish(tr_peer_event::GotPieceData(n_this_pass));
-+    *setme_piece_bytes_read += n_this_pass;
-+    incoming_block.n_bytes_received += n_this_pass;
-+    TR_ASSERT(incoming_block.n_bytes_received <= block_size);
-+    logtrace(msgs, fmt::format("got {:d} bytes for req {:d}:{:d}->{:d}", n_this_pass, req->index, req->offset, req->length));
-+
-+    // if we haven't gotten the full response yet,
-+    // update what part of `req` is unfulfilled and wait for more
-+    if (n_this_pass < req->length)
-+    {
-+        req->length -= n_this_pass;
-+        auto const new_loc = msgs->torrent->byteLoc(loc.byte + n_this_pass);
-         req->index = new_loc.piece;
-         req->offset = new_loc.piece_offset;
--        req->length -= n_to_read;
-         return READ_LATER;
-     }
- 
--    // we've fully read this message
-+    // we've got the entire response message
-     req.reset();
-     msgs->state = AwaitingBt::Length;
- 
--    // if we didn't read enough to finish off the block,
--    // update the table and wait for more
--    if (std::size(*block_buf) < block_size)
-+    // if we haven't gotten the entire block yet, wait for more
-+    if (incoming_block.n_bytes_received < block_size)
-     {
-         return READ_LATER;
-     }
- 
--    return clientGotBlock(msgs, block_buf, block) != 0 ? READ_ERR : READ_NOW;
-+    // we've got the entire block, so send it along.
-+    auto block_buf = std::move(incoming_block.buf);
-+    incoming.blocks.erase(block); // note: invalidates `incoming_block` local
-+    auto const ok = clientGotBlock(msgs, std::move(block_buf), block) == 0;
-+    return ok ? READ_NOW : READ_ERR;
- }
- 
- ReadState readBtMessage(tr_peerMsgsImpl* msgs, size_t inlen)
-@@ -1744,7 +1746,7 @@ ReadState readBtMessage(tr_peerMsgsImpl* msgs, size_t inlen)
- }
- 
- /* returns 0 on success, or an errno on failure */
--int clientGotBlock(tr_peerMsgsImpl* msgs, std::unique_ptr<std::vector<uint8_t>>& block_data, tr_block_index_t const block)
-+int clientGotBlock(tr_peerMsgsImpl* msgs, std::unique_ptr<std::vector<uint8_t>> block_data, tr_block_index_t const block)
- {
-     TR_ASSERT(msgs != nullptr);
- 
-@@ -1760,7 +1762,6 @@ int clientGotBlock(tr_peerMsgsImpl* msgs, std::unique_ptr<std::vector<uint8_t>>&
-     if (std::size(*block_data) != msgs->torrent->blockSize(block))
-     {
-         logdbg(msgs, fmt::format("wrong block size: expected {:d}, got {:d}", n_expected, std::size(*block_data)));
--        block_data->clear();
-         return EMSGSIZE;
-     }
- 
-@@ -1769,7 +1770,6 @@ int clientGotBlock(tr_peerMsgsImpl* msgs, std::unique_ptr<std::vector<uint8_t>>&
-     if (!tr_peerMgrDidPeerRequest(msgs->torrent, msgs, block))
-     {
-         logdbg(msgs, "we didn't ask for this message...");
--        block_data->clear();
-         return 0;
-     }
- 
-@@ -1777,19 +1777,17 @@ int clientGotBlock(tr_peerMsgsImpl* msgs, std::unique_ptr<std::vector<uint8_t>>&
-     if (msgs->torrent->hasPiece(loc.piece))
-     {
-         logtrace(msgs, "we did ask for this message, but the piece is already complete...");
--        block_data->clear();
-         return 0;
-     }
- 
-     // NB: if writeBlock() fails the torrent may be paused.
-     // If this happens, `msgs` will be a dangling pointer and must no longer be used.
--    if (auto const err = msgs->session->cache->writeBlock(tor->id(), block, block_data); err != 0)
-+    if (auto const err = msgs->session->cache->writeBlock(tor->id(), block, std::move(block_data)); err != 0)
-     {
-         return err;
-     }
- 
-     msgs->blame.set(loc.piece);
--    msgs->incoming.block_buf.erase(block);
-     msgs->publish(tr_peer_event::GotBlock(tor->blockInfo(), block));
- 
-     return 0;
-diff --git a/libtransmission/torrent.cc b/libtransmission/torrent.cc
-index 4b5a0b1dea..cd96bac2c3 100644
---- a/libtransmission/torrent.cc
-+++ b/libtransmission/torrent.cc
-@@ -2400,8 +2400,17 @@ void tr_torrentGotBlock(tr_torrent* tor, tr_block_index_t block)
-     tor->setDirty();
- 
-     tor->completion.addBlock(block);
--    if (auto const piece = tor->blockLoc(block).piece; tor->hasPiece(piece))
-+
-+    auto const block_loc = tor->blockLoc(block);
-+    auto const first_piece = block_loc.piece;
-+    auto const last_piece = tor->byteLoc(block_loc.byte + tor->blockSize(block) - 1).piece;
-+    for (auto piece = first_piece; piece <= last_piece; ++piece)
-     {
-+        if (!tor->hasPiece(piece))
-+        {
-+            continue;
-+        }
-+
-         if (tor->checkPiece(piece))
-         {
-             onPieceCompleted(tor, piece);
-diff --git a/libtransmission/webseed.cc b/libtransmission/webseed.cc
-index 7f07dd149e..8136139d87 100644
---- a/libtransmission/webseed.cc
-+++ b/libtransmission/webseed.cc
-@@ -352,7 +352,7 @@ struct write_block_data
-     {
-         if (auto const* const tor = tr_torrentFindFromId(session_, tor_id_); tor != nullptr)
-         {
--            session_->cache->writeBlock(tor_id_, block_, data_);
-+            session_->cache->writeBlock(tor_id_, block_, std::move(data_));
-             webseed_->publish(tr_peer_event::GotBlock(tor->blockInfo(), block_));
-         }
- 
-
-From 8a3418aae23e37d446a86b11a34679db0bfa99f7 Mon Sep 17 00:00:00 2001
-From: Charles Kerr <charles@charleskerr.com>
-Date: Tue, 14 Feb 2023 10:59:16 -0600
-Subject: [PATCH 2/3] fixup! fix: processing of block fragments that arrive
- out-of-order from request
-
-refactor: be more paranoid about duplicate requests at endgame.
----
- libtransmission/peer-msgs.cc | 16 ++++++++++------
- 1 file changed, 10 insertions(+), 6 deletions(-)
-
-diff --git a/libtransmission/peer-msgs.cc b/libtransmission/peer-msgs.cc
-index 05864fea20..24e3359d65 100644
---- a/libtransmission/peer-msgs.cc
-+++ b/libtransmission/peer-msgs.cc
-@@ -22,6 +22,7 @@
- 
- #include "transmission.h"
- 
-+#include "bitfield.h"
- #include "cache.h"
- #include "completion.h"
- #include "crypto-utils.h"
-@@ -193,12 +194,12 @@ struct tr_incoming
-     {
-         explicit incoming_piece_data(uint32_t block_size)
-             : buf{ std::make_unique<std::vector<uint8_t>>(block_size) }
-+            , have{ block_size }
-         {
-         }
- 
--        uint32_t n_bytes_received = 0;
--
-         std::unique_ptr<std::vector<uint8_t>> buf;
-+        tr_bitfield have;
-     };
- 
-     std::map<tr_block_index_t, incoming_piece_data> blocks;
-@@ -1443,19 +1444,22 @@ ReadState readBtPiece(tr_peerMsgsImpl* msgs, size_t inlen, size_t* setme_piece_b
- 
-     auto const n_this_pass = std::min(size_t{ req->length }, inlen);
-     TR_ASSERT(loc.block_offset + n_this_pass <= block_size);
-+    if (n_this_pass == 0)
-+    {
-+        return READ_LATER;
-+    }
- 
-     auto& incoming_block = incoming.blocks.try_emplace(block, block_size).first->second;
-     msgs->io->read_bytes(std::data(*incoming_block.buf) + loc.block_offset, n_this_pass);
- 
-     msgs->publish(tr_peer_event::GotPieceData(n_this_pass));
-     *setme_piece_bytes_read += n_this_pass;
--    incoming_block.n_bytes_received += n_this_pass;
--    TR_ASSERT(incoming_block.n_bytes_received <= block_size);
-+    incoming_block.have.setSpan(loc.block_offset, loc.block_offset + n_this_pass);
-     logtrace(msgs, fmt::format("got {:d} bytes for req {:d}:{:d}->{:d}", n_this_pass, req->index, req->offset, req->length));
- 
-     // if we haven't gotten the full response yet,
-     // update what part of `req` is unfulfilled and wait for more
--    if (n_this_pass < req->length)
-+    if (req->length > n_this_pass)
-     {
-         req->length -= n_this_pass;
-         auto const new_loc = msgs->torrent->byteLoc(loc.byte + n_this_pass);
-@@ -1469,7 +1473,7 @@ ReadState readBtPiece(tr_peerMsgsImpl* msgs, size_t inlen, size_t* setme_piece_b
-     msgs->state = AwaitingBt::Length;
- 
-     // if we haven't gotten the entire block yet, wait for more
--    if (incoming_block.n_bytes_received < block_size)
-+    if (!incoming_block.have.hasAll())
-     {
-         return READ_LATER;
-     }
-
-From d75445758c3e7dc666aba781111275d62acbf3b8 Mon Sep 17 00:00:00 2001
-From: Charles Kerr <charles@charleskerr.com>
-Date: Tue, 14 Feb 2023 11:57:35 -0600
-Subject: [PATCH 3/3] fixup! fix: processing of block fragments that arrive
- out-of-order from request
-
-chore: sync tests
----
- tests/libtransmission/move-test.cc | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/tests/libtransmission/move-test.cc b/tests/libtransmission/move-test.cc
-index cc5dc05ce6..e06d1daefd 100644
---- a/tests/libtransmission/move-test.cc
-+++ b/tests/libtransmission/move-test.cc
-@@ -84,7 +84,7 @@ TEST_P(IncompleteDirTest, incompleteDir)
- 
-     auto const test_incomplete_dir_threadfunc = [](TestIncompleteDirData* data) noexcept
-     {
--        data->session->cache->writeBlock(data->tor->id(), data->block, data->buf);
-+        data->session->cache->writeBlock(data->tor->id(), data->block, std::move(data->buf));
-         tr_torrentGotBlock(data->tor, data->block);
-         data->done = true;
-     };

diff --git a/f551b4adbff0d59557d61867d0b6518c50f5a73f.patch b/f551b4adbff0d59557d61867d0b6518c50f5a73f.patch
deleted file mode 100644
index fcc68e2..0000000
--- a/f551b4adbff0d59557d61867d0b6518c50f5a73f.patch
+++ /dev/null
@@ -1,500 +0,0 @@
-From f551b4adbff0d59557d61867d0b6518c50f5a73f Mon Sep 17 00:00:00 2001
-From: Charles Kerr <charles@charleskerr.com>
-Date: Mon, 13 Feb 2023 12:33:33 -0600
-Subject: [PATCH] fix: magnet links are always paused when added (#4856)
-
----
- libtransmission/peer-mgr.cc       |   8 +-
- libtransmission/resume.cc         |   6 +-
- libtransmission/torrent-magnet.cc |  34 +++----
- libtransmission/torrent-magnet.h  |   2 +
- libtransmission/torrent.cc        | 148 ++++++++++++++----------------
- libtransmission/torrent.h         |   9 +-
- libtransmission/transmission.h    |   2 +-
- macosx/Torrent.mm                 |   2 +-
- 8 files changed, 101 insertions(+), 110 deletions(-)
-
-diff --git a/libtransmission/peer-mgr.cc b/libtransmission/peer-mgr.cc
-index 4cf1d332c8..8e826dc3fa 100644
---- a/libtransmission/peer-mgr.cc
-+++ b/libtransmission/peer-mgr.cc
-@@ -43,6 +43,7 @@
- #include "session.h"
- #include "timer.h"
- #include "torrent.h"
-+#include "torrent-magnet.h"
- #include "tr-assert.h"
- #include "tr-utp.h"
- #include "utils.h"
-@@ -2391,8 +2392,11 @@ void tr_peerMgr::bandwidthPulse()
-     session->top_bandwidth_.allocate(Msec);
- 
-     // torrent upkeep
--    auto& torrents = session->torrents();
--    std::for_each(std::begin(torrents), std::end(torrents), [](auto* tor) { tor->do_idle_work(); });
-+    for (auto* const tor : session->torrents())
-+    {
-+        tor->do_idle_work();
-+        tr_torrentMagnetDoIdleWork(tor);
-+    }
- 
-     /* pump the queues */
-     queuePulse(session, TR_UP);
-diff --git a/libtransmission/resume.cc b/libtransmission/resume.cc
-index 80c00dbd28..9716ae876c 100644
---- a/libtransmission/resume.cc
-+++ b/libtransmission/resume.cc
-@@ -712,7 +712,7 @@ auto loadFromFile(tr_torrent* tor, tr_resume::fields_t fields_to_load, bool* did
- 
-     if (auto val = bool{}; (fields_to_load & tr_resume::Run) != 0 && tr_variantDictFindBool(&top, TR_KEY_paused, &val))
-     {
--        tor->isRunning = !val;
-+        tor->start_when_stable = !val;
-         fields_loaded |= tr_resume::Run;
-     }
- 
-@@ -831,7 +831,7 @@ auto setFromCtor(tr_torrent* tor, tr_resume::fields_t fields, tr_ctor const* cto
-     {
-         if (auto is_paused = bool{}; tr_ctorGetPaused(ctor, mode, &is_paused))
-         {
--            tor->isRunning = !is_paused;
-+            tor->start_when_stable = !is_paused;
-             ret |= tr_resume::Run;
-         }
-     }
-@@ -907,7 +907,7 @@ void save(tr_torrent* tor)
-     tr_variantDictAddInt(&top, TR_KEY_uploaded, tor->uploadedPrev + tor->uploadedCur);
-     tr_variantDictAddInt(&top, TR_KEY_max_peers, tor->peerLimit());
-     tr_variantDictAddInt(&top, TR_KEY_bandwidth_priority, tor->getPriority());
--    tr_variantDictAddBool(&top, TR_KEY_paused, !tor->isRunning && !tor->isQueued());
-+    tr_variantDictAddBool(&top, TR_KEY_paused, !tor->start_when_stable);
-     savePeers(&top, tor);
- 
-     if (tor->hasMetainfo())
-diff --git a/libtransmission/torrent-magnet.cc b/libtransmission/torrent-magnet.cc
-index 1d91cbfef1..c32defb433 100644
---- a/libtransmission/torrent-magnet.cc
-+++ b/libtransmission/torrent-magnet.cc
-@@ -176,13 +176,6 @@ bool tr_torrentUseMetainfoFromFile(
-         delete tor->incompleteMetadata;
-         tor->incompleteMetadata = nullptr;
-     }
--    tor->isStopping = true;
--    tor->magnetVerify = true;
--    if (tor->session->shouldPauseAddedTorrents())
--    {
--        tor->startAfterVerify = false;
--    }
--    tor->markEdited();
- 
-     return true;
- }
-@@ -310,13 +303,6 @@ void on_have_all_metainfo(tr_torrent* tor, tr_incomplete_metadata* m)
-     {
-         delete tor->incompleteMetadata;
-         tor->incompleteMetadata = nullptr;
--        tor->isStopping = true;
--        tor->magnetVerify = true;
--        if (tor->session->shouldPauseAddedTorrents() && !tor->magnetStartAfterVerify)
--        {
--            tor->startAfterVerify = false;
--        }
--        tor->markEdited();
-     }
-     else /* drat. */
-     {
-@@ -340,6 +326,19 @@ void on_have_all_metainfo(tr_torrent* tor, tr_incomplete_metadata* m)
- } // namespace set_metadata_piece_helpers
- } // namespace
- 
-+void tr_torrentMagnetDoIdleWork(tr_torrent* const tor)
-+{
-+    using namespace set_metadata_piece_helpers;
-+
-+    TR_ASSERT(tr_isTorrent(tor));
-+
-+    if (auto* const m = tor->incompleteMetadata; m != nullptr && std::empty(m->pieces_needed))
-+    {
-+        tr_logAddDebugTor(tor, fmt::format("we now have all the metainfo!"));
-+        on_have_all_metainfo(tor, m);
-+    }
-+}
-+
- void tr_torrentSetMetadataPiece(tr_torrent* tor, int piece, void const* data, size_t len)
- {
-     using namespace set_metadata_piece_helpers;
-@@ -384,13 +383,6 @@ void tr_torrentSetMetadataPiece(tr_torrent* tor, int piece, void const* data, si
- 
-     needed.erase(iter);
-     tr_logAddDebugTor(tor, fmt::format("saving metainfo piece {}... {} remain", piece, std::size(needed)));
--
--    // are we done?
--    if (std::empty(needed))
--    {
--        tr_logAddDebugTor(tor, fmt::format("metainfo piece {} was the last one", piece));
--        on_have_all_metainfo(tor, m);
--    }
- }
- 
- // ---
-diff --git a/libtransmission/torrent-magnet.h b/libtransmission/torrent-magnet.h
-index 8af953bec9..cb5d7e1fcb 100644
---- a/libtransmission/torrent-magnet.h
-+++ b/libtransmission/torrent-magnet.h
-@@ -33,6 +33,8 @@ bool tr_torrentSetMetadataSizeHint(tr_torrent* tor, int64_t metadata_size);
- 
- double tr_torrentGetMetadataPercent(tr_torrent const* tor);
- 
-+void tr_torrentMagnetDoIdleWork(tr_torrent* tor);
-+
- bool tr_torrentUseMetainfoFromFile(
-     tr_torrent* tor,
-     tr_torrent_metainfo const* metainfo,
-diff --git a/libtransmission/torrent.cc b/libtransmission/torrent.cc
-index 1e74f8152b..4b5a0b1dea 100644
---- a/libtransmission/torrent.cc
-+++ b/libtransmission/torrent.cc
-@@ -830,6 +830,8 @@ void torrentStart(tr_torrent* tor, torrent_start_opts opts)
- {
-     using namespace start_stop_helpers;
- 
-+    auto const lock = tor->unique_lock();
-+
-     switch (tor->activity())
-     {
-     case TR_STATUS_SEED:
-@@ -849,7 +851,6 @@ void torrentStart(tr_torrent* tor, torrent_start_opts opts)
-     case TR_STATUS_CHECK_WAIT:
-         /* verifying right now... wait until that's done so
-          * we'll know what completeness to use/announce */
--        tor->startAfterVerify = true;
-         return;
- 
-     case TR_STATUS_STOPPED:
-@@ -868,9 +869,6 @@ void torrentStart(tr_torrent* tor, torrent_start_opts opts)
-         return;
-     }
- 
--    /* otherwise, start it now... */
--    auto const lock = tor->unique_lock();
--
-     /* allow finished torrents to be resumed */
-     if (tr_torrentIsSeedRatioDone(tor))
-     {
-@@ -895,6 +893,9 @@ void torrentStop(tr_torrent* const tor)
-     TR_ASSERT(tor->session->amInSessionThread());
-     auto const lock = tor->unique_lock();
- 
-+    tor->isRunning = false;
-+    tor->isStopping = false;
-+
-     if (!tor->session->isClosing())
-     {
-         tr_logAddInfoTor(tor, _("Pausing torrent"));
-@@ -913,16 +914,6 @@ void torrentStop(tr_torrent* const tor)
-     }
- 
-     torrentSetQueued(tor, false);
--
--    if (tor->magnetVerify)
--    {
--        tor->magnetVerify = false;
--        tr_logAddTraceTor(tor, "Magnet Verify");
--        tor->refreshCurrentDir();
--        tr_torrentVerify(tor);
--
--        callScriptIfEnabled(tor, TR_SCRIPT_ON_TORRENT_ADDED);
--    }
- }
- } // namespace
- 
-@@ -935,8 +926,7 @@ void tr_torrentStop(tr_torrent* tor)
- 
-     auto const lock = tor->unique_lock();
- 
--    tor->isRunning = false;
--    tor->isStopping = false;
-+    tor->start_when_stable = false;
-     tor->setDirty();
-     tor->session->runInSessionThread(torrentStop, tor);
- }
-@@ -965,7 +955,6 @@ void tr_torrentFreeInSessionThread(tr_torrent* tor)
-         tr_logAddInfoTor(tor, _("Removing torrent"));
-     }
- 
--    tor->magnetVerify = false;
-     torrentStop(tor);
- 
-     if (tor->isDeleting)
-@@ -975,7 +964,6 @@ void tr_torrentFreeInSessionThread(tr_torrent* tor)
-         tr_torrent_metainfo::removeFile(tor->session->resumeDir(), tor->name(), tor->infoHashString(), ".resume"sv);
-     }
- 
--    tor->isRunning = false;
-     freeTorrent(tor);
- }
- 
-@@ -1036,6 +1024,34 @@ void torrentInitFromInfoDict(tr_torrent* tor)
-     tor->checked_pieces_ = tr_bitfield{ size_t(tor->pieceCount()) };
- }
- 
-+void on_metainfo_completed(tr_torrent* tor)
-+{
-+    // we can look for files now that we know what files are in the torrent
-+    tor->refreshCurrentDir();
-+
-+    callScriptIfEnabled(tor, TR_SCRIPT_ON_TORRENT_ADDED);
-+
-+    if (tor->session->shouldFullyVerifyAddedTorrents() || !isNewTorrentASeed(tor))
-+    {
-+        tr_torrentVerify(tor);
-+    }
-+    else
-+    {
-+        tor->completion.setHasAll();
-+        tor->doneDate = tor->addedDate;
-+        tor->recheckCompleteness();
-+
-+        if (tor->start_when_stable)
-+        {
-+            torrentStart(tor, {});
-+        }
-+        else if (tor->isRunning)
-+        {
-+            tr_torrentStop(tor);
-+        }
-+    }
-+}
-+
- void torrentInit(tr_torrent* tor, tr_ctor const* ctor)
- {
-     tr_session* session = tr_ctorGetSession(ctor);
-@@ -1081,7 +1097,7 @@ void torrentInit(tr_torrent* tor, tr_ctor const* ctor)
-     tor->anyDate = now;
- 
-     tr_resume::fields_t loaded = {};
--    if (tor->hasMetainfo())
-+
-     {
-         // tr_resume::load() calls a lot of tr_torrentSetFoo() methods
-         // that set things as dirty, but... these settings being loaded are
-@@ -1106,9 +1122,6 @@ void torrentInit(tr_torrent* tor, tr_ctor const* ctor)
- 
-     tor->refreshCurrentDir();
- 
--    bool const do_start = tor->isRunning;
--    tor->isRunning = false;
--
-     if ((loaded & tr_resume::Speedlimit) == 0)
-     {
-         tor->useSpeedLimit(TR_UP, false);
-@@ -1174,37 +1187,14 @@ void torrentInit(tr_torrent* tor, tr_ctor const* ctor)
- 
-     tor->torrent_announcer = session->announcer_->addTorrent(tor, &tr_torrent::onTrackerResponse);
- 
--    if (is_new_torrent)
-+    if (auto const has_metainfo = tor->hasMetainfo(); is_new_torrent && has_metainfo)
-     {
--        if (tor->hasMetainfo())
--        {
--            callScriptIfEnabled(tor, TR_SCRIPT_ON_TORRENT_ADDED);
--        }
--
--        if (!tor->hasMetainfo() && !do_start)
--        {
--            auto opts = torrent_start_opts{};
--            opts.bypass_queue = true;
--            opts.has_local_data = has_local_data;
--            torrentStart(tor, opts);
--        }
--        else if (!session->shouldFullyVerifyAddedTorrents() && isNewTorrentASeed(tor))
--        {
--            tor->completion.setHasAll();
--            tor->doneDate = tor->addedDate;
--            tor->recheckCompleteness();
--        }
--        else
--        {
--            tor->startAfterVerify = do_start;
--            tr_torrentVerify(tor);
--        }
-+        on_metainfo_completed(tor);
-     }
--    else if (do_start)
-+    else if (tor->start_when_stable || !has_metainfo)
-     {
--        // if checked_pieces_ got populated from the loading the resume
--        // file above, then torrentStart doesn't need to check again
-         auto opts = torrent_start_opts{};
-+        opts.bypass_queue = !has_metainfo; // to fetch metainfo from peers
-         opts.has_local_data = has_local_data;
-         torrentStart(tor, opts);
-     }
-@@ -1216,16 +1206,20 @@ void torrentInit(tr_torrent* tor, tr_ctor const* ctor)
- } // namespace torrent_init_helpers
- } // namespace
- 
--void tr_torrent::setMetainfo(tr_torrent_metainfo const& tm)
-+void tr_torrent::setMetainfo(tr_torrent_metainfo tm)
- {
-     using namespace torrent_init_helpers;
- 
--    metainfo_ = tm;
-+    TR_ASSERT(!hasMetainfo());
-+    metainfo_ = std::move(tm);
- 
-     torrentInitFromInfoDict(this);
-     tr_peerMgrOnTorrentGotMetainfo(this);
-     session->onMetadataCompleted(this);
-     this->setDirty();
-+    this->markEdited();
-+
-+    on_metainfo_completed(this);
- }
- 
- tr_torrent* tr_torrentNew(tr_ctor* ctor, tr_torrent** setme_duplicate_of)
-@@ -1763,33 +1757,35 @@ void tr_torrentAmountFinished(tr_torrent const* tor, float* tabs, int n_tabs)
- 
- // --- Start/Stop Callback
- 
--void tr_torrentStart(tr_torrent* tor)
-+namespace
-+{
-+void tr_torrentStartImpl(tr_torrent* tor, bool bypass_queue)
- {
--    if (tr_isTorrent(tor))
-+    if (!tr_isTorrent(tor))
-     {
--        tor->startAfterVerify = true;
--        torrentStart(tor, {});
-+        return;
-     }
-+
-+    tor->start_when_stable = true;
-+    auto opts = torrent_start_opts{};
-+    opts.bypass_queue = bypass_queue;
-+    torrentStart(tor, opts);
-+}
-+} // namespace
-+
-+void tr_torrentStart(tr_torrent* tor)
-+{
-+    tr_torrentStartImpl(tor, false);
- }
- 
- void tr_torrentStartNow(tr_torrent* tor)
- {
--    if (tr_isTorrent(tor))
--    {
--        auto opts = torrent_start_opts{};
--        opts.bypass_queue = true;
--        torrentStart(tor, opts);
--    }
-+    tr_torrentStartImpl(tor, true);
- }
- 
- void tr_torrentStartMagnet(tr_torrent* tor)
- {
--    if (tr_isTorrent(tor))
--    {
--        tor->magnetStartAfterVerify = true;
--        tor->startAfterVerify = true;
--        torrentStart(tor, {});
--    }
-+    tr_torrentStart(tor);
- }
- 
- // ---
-@@ -1809,10 +1805,8 @@ void onVerifyDoneThreadFunc(tr_torrent* const tor)
- 
-     tor->recheckCompleteness();
- 
--    if (tor->startAfterVerify)
-+    if (tor->start_when_stable)
-     {
--        tor->startAfterVerify = false;
--
-         auto opts = torrent_start_opts{};
-         opts.has_local_data = !tor->checked_pieces_.hasNone();
-         torrentStart(tor, opts);
-@@ -1832,20 +1826,18 @@ void verifyTorrent(tr_torrent* const tor)
-     /* if the torrent's already being verified, stop it */
-     tor->session->verifyRemove(tor);
- 
--    bool const start_after = (tor->isRunning || tor->startAfterVerify) && !tor->isStopping;
--
--    if (tor->isRunning)
-+    if (!tor->hasMetainfo())
-     {
--        tr_torrentStop(tor);
-+        return;
-     }
- 
--    if (setLocalErrorIfFilesDisappeared(tor))
-+    if (tor->isRunning)
-     {
--        tor->startAfterVerify = false;
-+        torrentStop(tor);
-     }
--    else
-+
-+    if (!setLocalErrorIfFilesDisappeared(tor))
-     {
--        tor->startAfterVerify = start_after;
-         tor->session->verifyAdd(tor);
-     }
- }
-diff --git a/libtransmission/torrent.h b/libtransmission/torrent.h
-index deebb77337..a1a3031aa8 100644
---- a/libtransmission/torrent.h
-+++ b/libtransmission/torrent.h
-@@ -109,7 +109,8 @@ struct tr_torrent final : public tr_completion::torrent_view
-     // but more refactoring is needed before that can happen
-     // because much of tr_torrent's impl is in the non-member C bindings
- 
--    void setMetainfo(tr_torrent_metainfo const& tm);
-+    // Used to add metainfo to a magnet torrent.
-+    void setMetainfo(tr_torrent_metainfo tm);
- 
-     [[nodiscard]] auto unique_lock() const
-     {
-@@ -903,10 +904,10 @@ struct tr_torrent final : public tr_completion::torrent_view
-     bool is_queued = false;
-     bool isRunning = false;
-     bool isStopping = false;
--    bool startAfterVerify = false;
--    bool magnetStartAfterVerify = false;
- 
--    bool magnetVerify = false;
-+    // start the torrent after all the startup scaffolding is done,
-+    // e.g. fetching metadata from peers and/or verifying the torrent
-+    bool start_when_stable = false;
- 
- private:
-     [[nodiscard]] constexpr bool isPieceTransferAllowed(tr_direction direction) const noexcept
-diff --git a/libtransmission/transmission.h b/libtransmission/transmission.h
-index 11bb8743dd..82bf1d5e54 100644
---- a/libtransmission/transmission.h
-+++ b/libtransmission/transmission.h
-@@ -601,7 +601,7 @@ void tr_sessionSetAntiBruteForceEnabled(tr_session* session, bool enabled);
- /** @brief Like `tr_torrentStart()`, but resumes right away regardless of the queues. */
- void tr_torrentStartNow(tr_torrent* tor);
- 
--/** @brief Like tr_torrentStart(), but sets magnetStartAfterVerify to true. */
-+/** @brief DEPRECATED. Equivalent to tr_torrentStart(). Use that instead. */
- void tr_torrentStartMagnet(tr_torrent*);
- 
- /** @brief Return the queued torrent's position in the queue it's in. [0...n) */
-diff --git a/macosx/Torrent.mm b/macosx/Torrent.mm
-index bd5ad7972f..98e69882d3 100644
---- a/macosx/Torrent.mm
-+++ b/macosx/Torrent.mm
-@@ -280,7 +280,7 @@ - (void)startMagnetTransferAfterMetaDownload
- {
-     if ([self alertForRemainingDiskSpace])
-     {
--        tr_torrentStartMagnet(self.fHandle);
-+        tr_torrentStart(self.fHandle);
-         [self update];
- 
-         //capture, specifically, stop-seeding settings changing to unlimited

diff --git a/sources b/sources
index 83b59f4..8053cb5 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-SHA512 (transmission-4.0.0.tar.xz) = 79945af73fe7226dddadba7cc039516f2f878e05a9cf6c6d799b636b8298e2b2fa25c4426789bd41ef4d2b00d75a3c1c115c1676b4d2a9f09a1526456dceb3f8
+SHA512 (transmission-4.0.1.tar.xz) = a0226c96b08fd7be7cb9763132e36e59a4f84d67277c345860ac5a2e685ec0d5f2e8b3fe1e2d090e1180499518084de99387b822bb6dbdc1b7cb076d9a99ce05

diff --git a/transmission.spec b/transmission.spec
index 4f3e0f4..4238fff 100644
--- a/transmission.spec
+++ b/transmission.spec
@@ -1,8 +1,8 @@
 %global _hardened_build 1
 
 Name:           transmission
-Version:        4.0.0
-Release:        3%{?dist}
+Version:        4.0.1
+Release:        1%{?dist}
 Summary:        A lightweight GTK+ BitTorrent client
 # See COPYING. This licensing situation is... special.
 License:        MIT and GPLv2
@@ -11,11 +11,9 @@ URL:            http://www.transmissionbt.com
 Source0:        https://github.com/transmission/transmission/releases/download/%{version}/transmission-%{version}.tar.xz
 # https://bugzilla.redhat.com/show_bug.cgi?id=1221292
 Source1:        https://raw.githubusercontent.com/gnome-design-team/gnome-icons/master/apps-symbolic/Adwaita/scalable/apps/transmission-symbolic.svg
-Patch0:         f551b4adbff0d59557d61867d0b6518c50f5a73f.patch
-Patch1:         4890.patch
 # Fix the DBus name to match the app name for flatpak builds
 # https://github.com/transmission/transmission/pull/847
-Patch2:         0001-gtk-use-com.transmissionbt.Transmission.-D-Bus-names.patch
+Patch0:         0001-gtk-use-com.transmissionbt.Transmission.-D-Bus-names.patch
 
 
 BuildRequires:  make
@@ -182,6 +180,9 @@ desktop-file-install \
 %doc %{_mandir}/man1/transmission-qt.*
 
 %changelog
+* Thu Feb 23 2023 Gwyn Ciesla <gwync@protonmail.com> - 4.0.1-1
+- 4.0.1
+
 * Wed Feb 15 2023 Kalev Lember <klember@redhat.com> - 4.0.0-3
 - Avoid hardcoding /usr prefix
 - Restore flatpak DBus name patch

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-07-20 20:37 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-07-20 20:37 [rpms/transmission] epel10: 4.0.1 Gwyn Ciesla

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox