mirror of
https://github.com/transmission/transmission
synced 2025-03-09 05:14:09 +00:00
refactor: pause torrent after verifying if files disappeared (#6277)
This commit is contained in:
parent
b977ac77ca
commit
7af71d9695
10 changed files with 42 additions and 142 deletions
|
@ -112,14 +112,13 @@ username and password (respectively), separated by a colon.
|
|||
|
||||
## 3 Torrent requests
|
||||
### 3.1 Torrent action requests
|
||||
| Method name | libtransmission function
|
||||
| Method name | libtransmission function
|
||||
|:--|:--
|
||||
| `torrent-start` | tr_torrentStart
|
||||
| `torrent-start-now` | tr_torrentStartNow
|
||||
| `torrent-stop` | tr_torrentStop
|
||||
| `torrent-verify` | tr_torrentVerify
|
||||
| `torrent-verify-force` | tr_torrentVerifyForce
|
||||
| `torrent-reannounce` | tr_torrentManualUpdate ("ask tracker for more peers")
|
||||
| `torrent-start` | tr_torrentStart
|
||||
| `torrent-start-now` | tr_torrentStartNow
|
||||
| `torrent-stop` | tr_torrentStop
|
||||
| `torrent-verify` | tr_torrentVerify
|
||||
| `torrent-reannounce` | tr_torrentManualUpdate ("ask tracker for more peers")
|
||||
|
||||
Request arguments: `ids`, which specifies which torrents to use.
|
||||
All torrents are used if the `ids` argument is omitted.
|
||||
|
@ -1026,4 +1025,3 @@ Transmission 4.1.0 (`rpc-version-semver` 5.4.0, `rpc-version`: 18)
|
|||
| `torrent-get` | new arg `files.beginPiece`
|
||||
| `torrent-get` | new arg `files.endPiece`
|
||||
| `port-test` | new arg `ipProtocol`
|
||||
| `torrent-verify-force` | new method
|
||||
|
|
|
@ -282,33 +282,16 @@ char const* torrentReannounce(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
namespace torrent_verify_helpers
|
||||
{
|
||||
char const* torrentVerifyImpl(tr_session* session, tr_variant* args_in, bool force)
|
||||
char const* torrentVerify(tr_session* session, tr_variant* args_in, tr_variant* /*args_out*/, tr_rpc_idle_data* /*idle_data*/)
|
||||
{
|
||||
for (auto* tor : getTorrents(session, args_in))
|
||||
{
|
||||
tr_torrentVerify(tor, force);
|
||||
tr_torrentVerify(tor);
|
||||
session->rpcNotify(TR_RPC_TORRENT_CHANGED, tor);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
} // namespace torrent_verify_helpers
|
||||
|
||||
char const* torrentVerify(tr_session* session, tr_variant* args_in, tr_variant* /*args_out*/, tr_rpc_idle_data* /*idle_data*/)
|
||||
{
|
||||
return torrent_verify_helpers::torrentVerifyImpl(session, args_in, false);
|
||||
}
|
||||
|
||||
char const* torrentVerifyForce(
|
||||
tr_session* session,
|
||||
tr_variant* args_in,
|
||||
tr_variant* /*args_out*/,
|
||||
tr_rpc_idle_data* /*idle_data*/)
|
||||
{
|
||||
return torrent_verify_helpers::torrentVerifyImpl(session, args_in, true);
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
|
@ -2341,7 +2324,7 @@ struct rpc_method
|
|||
handler func;
|
||||
};
|
||||
|
||||
auto constexpr Methods = std::array<rpc_method, 25>{ {
|
||||
auto constexpr Methods = std::array<rpc_method, 24>{ {
|
||||
{ "blocklist-update"sv, false, blocklistUpdate },
|
||||
{ "free-space"sv, true, freeSpace },
|
||||
{ "group-get"sv, true, groupGet },
|
||||
|
@ -2366,7 +2349,6 @@ auto constexpr Methods = std::array<rpc_method, 25>{ {
|
|||
{ "torrent-start-now"sv, true, torrentStartNow },
|
||||
{ "torrent-stop"sv, true, torrentStop },
|
||||
{ "torrent-verify"sv, true, torrentVerify },
|
||||
{ "torrent-verify-force"sv, true, torrentVerifyForce },
|
||||
} };
|
||||
|
||||
void noop_response_callback(tr_session* /*session*/, tr_variant* /*response*/, void* /*user_data*/)
|
||||
|
|
|
@ -148,16 +148,22 @@ bool tr_torrentSetMetainfoFromFile(tr_torrent* tor, tr_torrent_metainfo const* m
|
|||
|
||||
namespace
|
||||
{
|
||||
bool setLocalErrorIfFilesDisappeared(tr_torrent* tor, std::optional<bool> has_local_data = {})
|
||||
bool did_files_disappear(tr_torrent* tor, std::optional<bool> has_local_data = {})
|
||||
{
|
||||
auto const has = has_local_data ? *has_local_data : tor->has_any_local_data();
|
||||
bool const files_disappeared = tor->has_total() > 0 && !has;
|
||||
return tor->has_total() > 0 && !has;
|
||||
}
|
||||
|
||||
bool set_local_error_if_files_disappeared(tr_torrent* tor, std::optional<bool> has_local_data = {})
|
||||
{
|
||||
auto const files_disappeared = did_files_disappear(tor, has_local_data);
|
||||
|
||||
if (files_disappeared)
|
||||
{
|
||||
tr_logAddTraceTor(tor, "[LAZY] uh oh, the files disappeared");
|
||||
tor->error().set_local_error(_(
|
||||
"No data found! Ensure your drives are connected or use \"Set Location\". To re-download, remove the torrent and re-add it."));
|
||||
tor->error().set_local_error(
|
||||
_("No data found! Ensure your drives are connected or use \"Set Location\". "
|
||||
"To re-download, use \"Verify Local Data\" and start the torrent afterwards."));
|
||||
}
|
||||
|
||||
return files_disappeared;
|
||||
|
@ -735,7 +741,7 @@ void torrentStart(tr_torrent* tor, torrent_start_opts opts)
|
|||
}
|
||||
|
||||
/* don't allow the torrent to be started if the files disappeared */
|
||||
if (setLocalErrorIfFilesDisappeared(tor, opts.has_local_data))
|
||||
if (set_local_error_if_files_disappeared(tor, opts.has_local_data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -1072,7 +1078,7 @@ void tr_torrent::init(tr_ctor const* const ctor)
|
|||
}
|
||||
else
|
||||
{
|
||||
setLocalErrorIfFilesDisappeared(this, has_local_data);
|
||||
set_local_error_if_files_disappeared(this, has_local_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1578,10 +1584,10 @@ void tr_torrentStartMagnet(tr_torrent* tor)
|
|||
|
||||
// ---
|
||||
|
||||
void tr_torrentVerify(tr_torrent* tor, bool force)
|
||||
void tr_torrentVerify(tr_torrent* tor)
|
||||
{
|
||||
tor->session->runInSessionThread(
|
||||
[tor, force]()
|
||||
[tor]()
|
||||
{
|
||||
TR_ASSERT(tor->session->am_in_session_thread());
|
||||
auto const lock = tor->unique_lock();
|
||||
|
@ -1603,10 +1609,15 @@ void tr_torrentVerify(tr_torrent* tor, bool force)
|
|||
tor->stop_now();
|
||||
}
|
||||
|
||||
if (force || !setLocalErrorIfFilesDisappeared(tor))
|
||||
if (did_files_disappear(tor))
|
||||
{
|
||||
tor->session->verify_add(tor);
|
||||
tor->error().set_local_error(
|
||||
_("Paused torrent as no data was found! Ensure your drives are connected or use \"Set Location\", "
|
||||
"then use \"Verify Local Data\" again. To re-download, start the torrent."));
|
||||
tor->start_when_stable = false;
|
||||
}
|
||||
|
||||
tor->session->verify_add(tor);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -2271,7 +2282,7 @@ void tr_torrent::set_download_dir(std::string_view path, bool is_new_torrent)
|
|||
recheck_completeness();
|
||||
}
|
||||
}
|
||||
else if (error_.error_type() == TR_STAT_LOCAL_ERROR && !setLocalErrorIfFilesDisappeared(this))
|
||||
else if (error_.error_type() == TR_STAT_LOCAL_ERROR && !set_local_error_if_files_disappeared(this))
|
||||
{
|
||||
error_.clear();
|
||||
}
|
||||
|
|
|
@ -1058,7 +1058,7 @@ private:
|
|||
friend void tr_torrentGotBlock(tr_torrent* tor, tr_block_index_t block);
|
||||
friend void tr_torrentRemove(tr_torrent* tor, bool delete_flag, tr_fileFunc delete_func, void* user_data);
|
||||
friend void tr_torrentStop(tr_torrent* tor);
|
||||
friend void tr_torrentVerify(tr_torrent* tor, bool force);
|
||||
friend void tr_torrentVerify(tr_torrent* tor);
|
||||
|
||||
enum class VerifyState : uint8_t
|
||||
{
|
||||
|
|
|
@ -1386,7 +1386,7 @@ void tr_torrentAmountFinished(tr_torrent const* torrent, float* tab, int n_tabs)
|
|||
/**
|
||||
* Queue a torrent for verification.
|
||||
*/
|
||||
void tr_torrentVerify(tr_torrent* torrent, bool force = false);
|
||||
void tr_torrentVerify(tr_torrent* torrent);
|
||||
|
||||
bool tr_torrentHasMetadata(tr_torrent const* tor);
|
||||
|
||||
|
|
|
@ -88,10 +88,6 @@ export class ActionManager extends EventTarget {
|
|||
shortcut: 'V',
|
||||
text: 'Verify local data',
|
||||
},
|
||||
'verify-selected-torrents-force': {
|
||||
enabled: false,
|
||||
text: 'Verify local data (force)',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -205,7 +201,6 @@ export class ActionManager extends EventTarget {
|
|||
'show-move-dialog',
|
||||
'trash-selected-torrents',
|
||||
'verify-selected-torrents',
|
||||
'verify-selected-torrents-force',
|
||||
]);
|
||||
|
||||
set_enabled(counts.selected === 1, ['show-rename-dialog']);
|
||||
|
|
|
@ -95,7 +95,6 @@ export class ContextMenu extends EventTarget {
|
|||
add_item('trash-selected-torrents', true);
|
||||
add_separator();
|
||||
add_item('verify-selected-torrents');
|
||||
add_item('verify-selected-torrents-force');
|
||||
add_item('show-move-dialog');
|
||||
add_item('show-rename-dialog');
|
||||
add_item('show-labels-dialog');
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
/* @license This file Copyright © Mnemosyne LLC.
|
||||
It may be used under GPLv2 (SPDX: GPL-2.0-only), GPLv3 (SPDX: GPL-3.0-only),
|
||||
or any future license endorsed by Mnemosyne LLC.
|
||||
License text can be found in the licenses/ folder. */
|
||||
|
||||
import { createDialogContainer } from './utils.js';
|
||||
|
||||
export class ForceVerifyDialog extends EventTarget {
|
||||
constructor(options) {
|
||||
super();
|
||||
|
||||
// options: remote, torrents, callback, controller
|
||||
this.options = options;
|
||||
this.elements = ForceVerifyDialog._create(options);
|
||||
this.elements.dismiss.addEventListener('click', () => this._onDismiss());
|
||||
this.elements.confirm.addEventListener('click', () => this._onConfirm());
|
||||
document.body.append(this.elements.root);
|
||||
this.elements.dismiss.focus();
|
||||
}
|
||||
|
||||
close() {
|
||||
if (!this.closed) {
|
||||
this.elements.root.remove();
|
||||
this.dispatchEvent(new Event('close'));
|
||||
for (const key of Object.keys(this)) {
|
||||
delete this[key];
|
||||
}
|
||||
this.closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
_onDismiss() {
|
||||
this.close();
|
||||
}
|
||||
|
||||
_onConfirm() {
|
||||
const { remote, torrents, callback, controller } = this.options;
|
||||
if (torrents.length > 0) {
|
||||
remote.verifyTorrents(
|
||||
torrents.map((t) => t.getId()),
|
||||
true,
|
||||
callback,
|
||||
controller,
|
||||
);
|
||||
}
|
||||
|
||||
this.close();
|
||||
}
|
||||
|
||||
static _create(options) {
|
||||
const { heading, message } = ForceVerifyDialog._createMessage(options);
|
||||
|
||||
const elements = createDialogContainer('remove-dialog');
|
||||
elements.heading.textContent = heading;
|
||||
elements.message.textContent = message;
|
||||
elements.confirm.textContent = 'Verify';
|
||||
return elements;
|
||||
}
|
||||
|
||||
static _createMessage(options) {
|
||||
const { torrents } = options;
|
||||
const heading =
|
||||
torrents.length === 1
|
||||
? `Force verify local data of ${torrents[0].getName()}?`
|
||||
: `Force verify local data of ${torrents.length} transfers?`;
|
||||
const message = `Missing files will be re-downloaded, use the non-forced verify function if you'd like to check for missing files.`;
|
||||
return { heading, message };
|
||||
}
|
||||
}
|
|
@ -227,9 +227,9 @@ export class Remote {
|
|||
this._controller.refreshTorrents();
|
||||
});
|
||||
}
|
||||
verifyTorrents(torrent_ids, force, callback, context) {
|
||||
verifyTorrents(torrent_ids, callback, context) {
|
||||
this.sendTorrentActionRequests(
|
||||
force ? 'torrent-verify-force' : 'torrent-verify',
|
||||
'torrent-verify',
|
||||
torrent_ids,
|
||||
callback,
|
||||
context,
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
import { AboutDialog } from './about-dialog.js';
|
||||
import { ContextMenu } from './context-menu.js';
|
||||
import { ForceVerifyDialog } from './force-verify-dialog';
|
||||
import { Formatter } from './formatter.js';
|
||||
import { Inspector } from './inspector.js';
|
||||
import { MoveDialog } from './move-dialog.js';
|
||||
|
@ -175,10 +174,7 @@ export class Transmission extends EventTarget {
|
|||
this._removeSelectedTorrents(true);
|
||||
break;
|
||||
case 'verify-selected-torrents':
|
||||
this._verifyTorrents(this.getSelectedTorrents(), false);
|
||||
break;
|
||||
case 'verify-selected-torrents-force':
|
||||
this._verifyTorrents(this.getSelectedTorrents(), true);
|
||||
this._verifyTorrents(this.getSelectedTorrents());
|
||||
break;
|
||||
default:
|
||||
console.warn(`unhandled action: ${event_.action}`);
|
||||
|
@ -857,24 +853,12 @@ TODO: fix this when notifications get fixed
|
|||
this,
|
||||
);
|
||||
}
|
||||
_verifyTorrents(torrents, force) {
|
||||
if (force) {
|
||||
this.setCurrentPopup(
|
||||
new ForceVerifyDialog({
|
||||
callback: this.refreshTorrents,
|
||||
controller: this,
|
||||
remote: this.remote,
|
||||
torrents,
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
this.remote.verifyTorrents(
|
||||
Transmission._getTorrentIds(torrents),
|
||||
force,
|
||||
this.refreshTorrents,
|
||||
this,
|
||||
);
|
||||
}
|
||||
_verifyTorrents(torrents) {
|
||||
this.remote.verifyTorrents(
|
||||
Transmission._getTorrentIds(torrents),
|
||||
this.refreshTorrents,
|
||||
this,
|
||||
);
|
||||
}
|
||||
|
||||
_reannounceTorrents(torrents) {
|
||||
|
|
Loading…
Add table
Reference in a new issue