diff --git a/docs/rpc-spec.md b/docs/rpc-spec.md index 4e083ef8c..b168c107e 100644 --- a/docs/rpc-spec.md +++ b/docs/rpc-spec.md @@ -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 diff --git a/libtransmission/rpcimpl.cc b/libtransmission/rpcimpl.cc index 3ceba77ac..e4eee01dc 100644 --- a/libtransmission/rpcimpl.cc +++ b/libtransmission/rpcimpl.cc @@ -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{ { +auto constexpr Methods = std::array{ { { "blocklist-update"sv, false, blocklistUpdate }, { "free-space"sv, true, freeSpace }, { "group-get"sv, true, groupGet }, @@ -2366,7 +2349,6 @@ auto constexpr Methods = std::array{ { { "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*/) diff --git a/libtransmission/torrent.cc b/libtransmission/torrent.cc index ae73785f9..52ef23871 100644 --- a/libtransmission/torrent.cc +++ b/libtransmission/torrent.cc @@ -148,16 +148,22 @@ bool tr_torrentSetMetainfoFromFile(tr_torrent* tor, tr_torrent_metainfo const* m namespace { -bool setLocalErrorIfFilesDisappeared(tr_torrent* tor, std::optional has_local_data = {}) +bool did_files_disappear(tr_torrent* tor, std::optional 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 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(); } diff --git a/libtransmission/torrent.h b/libtransmission/torrent.h index 1acbaa166..8a9a0d3bd 100644 --- a/libtransmission/torrent.h +++ b/libtransmission/torrent.h @@ -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 { diff --git a/libtransmission/transmission.h b/libtransmission/transmission.h index 40d6f520d..cf7b4f5fd 100644 --- a/libtransmission/transmission.h +++ b/libtransmission/transmission.h @@ -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); diff --git a/web/src/action-manager.js b/web/src/action-manager.js index 002409428..4b64cf76c 100644 --- a/web/src/action-manager.js +++ b/web/src/action-manager.js @@ -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']); diff --git a/web/src/context-menu.js b/web/src/context-menu.js index af326222c..309135269 100644 --- a/web/src/context-menu.js +++ b/web/src/context-menu.js @@ -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'); diff --git a/web/src/force-verify-dialog.js b/web/src/force-verify-dialog.js deleted file mode 100644 index b894a03a9..000000000 --- a/web/src/force-verify-dialog.js +++ /dev/null @@ -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 }; - } -} diff --git a/web/src/remote.js b/web/src/remote.js index 015b1779c..00835012c 100644 --- a/web/src/remote.js +++ b/web/src/remote.js @@ -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, diff --git a/web/src/transmission.js b/web/src/transmission.js index caca0517e..7b10f8d93 100644 --- a/web/src/transmission.js +++ b/web/src/transmission.js @@ -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) {