fix: only append '.added' suffix to watchdir files (#5705)

This commit is contained in:
Charles Kerr 2023-11-04 13:14:08 -05:00
parent 4da965365c
commit 4b10f67ad1
8 changed files with 83 additions and 41 deletions

View File

@ -124,3 +124,28 @@ QString AddData::readableShortName() const
return readableName(); return readableName();
} }
} }
void AddData::disposeSourceFile() const
{
auto file = QFile{ filename };
if (!disposal_ || !file.exists())
{
return;
}
switch (*disposal_)
{
case FilenameDisposal::Delete:
file.setPermissions(QFile::ReadOwner | QFile::WriteOwner);
file.remove();
break;
case FilenameDisposal::Rename:
file.rename(QStringLiteral("%1.added").arg(filename));
break;
default:
// no action
break;
}
}

View File

@ -14,6 +14,14 @@
class AddData class AddData
{ {
public: public:
// what to do with the source file after adding the torrent
enum class FilenameDisposal
{
NoAction,
Delete,
Rename
};
enum enum
{ {
NONE, NONE,
@ -36,6 +44,18 @@ public:
QString readableName() const; QString readableName() const;
QString readableShortName() const; QString readableShortName() const;
void disposeSourceFile() const;
constexpr void setFileDisposal(FilenameDisposal disposal)
{
disposal_ = disposal;
}
constexpr auto& fileDisposal() const noexcept
{
return disposal_;
}
static std::optional<AddData> create(QString const& str) static std::optional<AddData> create(QString const& str)
{ {
if (auto ret = AddData{ str }; ret.type != NONE) if (auto ret = AddData{ str }; ret.type != NONE)
@ -51,4 +71,7 @@ public:
QString filename; QString filename;
QString magnet; QString magnet;
QUrl url; QUrl url;
private:
std::optional<FilenameDisposal> disposal_;
}; };

View File

@ -287,7 +287,7 @@ Application::Application(int& argc, char** argv)
connect(session_.get(), &Session::sourceChanged, this, &Application::onSessionSourceChanged); connect(session_.get(), &Session::sourceChanged, this, &Application::onSessionSourceChanged);
connect(session_.get(), &Session::torrentsRemoved, model_.get(), &TorrentModel::removeTorrents); connect(session_.get(), &Session::torrentsRemoved, model_.get(), &TorrentModel::removeTorrents);
connect(session_.get(), &Session::torrentsUpdated, model_.get(), &TorrentModel::updateTorrents); connect(session_.get(), &Session::torrentsUpdated, model_.get(), &TorrentModel::updateTorrents);
connect(watch_dir_.get(), &WatchDir::torrentFileAdded, this, qOverload<QString const&>(&Application::addTorrent)); connect(watch_dir_.get(), &WatchDir::torrentFileAdded, this, qOverload<QString const&>(&Application::addWatchdirTorrent));
// init from preferences // init from preferences
for (auto const key : { Prefs::DIR_WATCH }) for (auto const key : { Prefs::DIR_WATCH })
@ -345,9 +345,10 @@ Application::Application(int& argc, char** argv)
dialog->show(); dialog->show();
} }
// torrent files passed in on the command line
for (QString const& filename : filenames) for (QString const& filename : filenames)
{ {
addTorrent(filename); addTorrent(AddData{ filename });
} }
InteropHelper::registerObject(this); InteropHelper::registerObject(this);
@ -574,18 +575,29 @@ void Application::refreshTorrents()
**** ****
***/ ***/
void Application::addTorrent(QString const& addme) const void Application::addWatchdirTorrent(QString const& filename) const
{ {
addTorrent(AddData(addme)); auto add_data = AddData{ filename };
auto const disposal = prefs_->getBool(Prefs::TRASH_ORIGINAL) ? AddData::FilenameDisposal::Delete :
AddData::FilenameDisposal::Rename;
add_data.setFileDisposal(disposal);
addTorrent(std::move(add_data));
} }
void Application::addTorrent(AddData const& addme) const void Application::addTorrent(AddData addme) const
{ {
if (addme.type == addme.NONE) if (addme.type == addme.NONE)
{ {
return; return;
} }
// if there's not already a disposal action set,
// then honor the `trash original` preference setting
if (!addme.fileDisposal() && prefs_->getBool(Prefs::TRASH_ORIGINAL))
{
addme.setFileDisposal(AddData::FilenameDisposal::Delete);
}
if (!prefs_->getBool(Prefs::OPTIONS_PROMPT)) if (!prefs_->getBool(Prefs::OPTIONS_PROMPT))
{ {
session_->addTorrent(addme); session_->addTorrent(addme);

View File

@ -16,6 +16,7 @@
#include <libtransmission/tr-macros.h> #include <libtransmission/tr-macros.h>
#include "AddData.h"
#include "FaviconCache.h" #include "FaviconCache.h"
#include "Typedefs.h" #include "Typedefs.h"
#include "Utils.h" // std::hash<QString> #include "Utils.h" // std::hash<QString>
@ -47,8 +48,8 @@ public:
FaviconCache& faviconCache(); FaviconCache& faviconCache();
public slots: public slots:
void addTorrent(AddData const&) const; void addTorrent(AddData) const;
void addTorrent(QString const&) const; void addWatchdirTorrent(QString const& filename) const;
private slots: private slots:
void consentGiven(int result) const; void consentGiven(int result) const;

View File

@ -1316,9 +1316,7 @@ void MainWindow::addTorrents(QStringList const& filenames)
if (auto const* const file_dialog = qobject_cast<QFileDialog const*>(sender()); file_dialog != nullptr) if (auto const* const file_dialog = qobject_cast<QFileDialog const*>(sender()); file_dialog != nullptr)
{ {
auto const* const b = file_dialog->findChild<QCheckBox const*>(show_options_checkbox_name_); if (auto const* const b = file_dialog->findChild<QCheckBox const*>(show_options_checkbox_name_); b != nullptr)
if (b != nullptr)
{ {
show_options = b->isChecked(); show_options = b->isChecked();
} }
@ -1326,7 +1324,7 @@ void MainWindow::addTorrents(QStringList const& filenames)
for (QString const& filename : filenames) for (QString const& filename : filenames)
{ {
addTorrent(AddData(filename), show_options); addTorrent(AddData{ filename }, show_options);
} }
} }
@ -1595,7 +1593,7 @@ void MainWindow::dropEvent(QDropEvent* event)
key = url.toLocalFile(); key = url.toLocalFile();
} }
trApp->addTorrent(AddData(key)); trApp->addTorrent(AddData{ key });
} }
} }
} }
@ -1626,7 +1624,7 @@ bool MainWindow::event(QEvent* e)
if (!clipboard_processed_keys_.contains(key)) if (!clipboard_processed_keys_.contains(key))
{ {
clipboard_processed_keys_.append(key); clipboard_processed_keys_.append(key);
trApp->addTorrent(AddData(key)); trApp->addTorrent(AddData{ key });
} }
} }
} }

View File

@ -297,7 +297,10 @@ void OptionsDialog::onAccepted()
} }
} }
session_.addTorrent(add_, &args, ui_.trashCheck->isChecked()); auto const disposal = ui_.trashCheck->isChecked() ? AddData::FilenameDisposal::Delete : AddData::FilenameDisposal::NoAction;
add_.setFileDisposal(disposal);
session_.addTorrent(add_, &args);
deleteLater(); deleteLater();
} }

View File

@ -992,7 +992,7 @@ void Session::setBlocklistSize(int64_t i)
emit blocklistUpdated(i); emit blocklistUpdated(i);
} }
void Session::addTorrent(AddData add_me, tr_variant* args_dict, bool trash_original) void Session::addTorrent(AddData add_me, tr_variant* args_dict)
{ {
assert(tr_variantDictFind(args_dict, TR_KEY_filename) == nullptr); assert(tr_variantDictFind(args_dict, TR_KEY_filename) == nullptr);
assert(tr_variantDictFind(args_dict, TR_KEY_metainfo) == nullptr); assert(tr_variantDictFind(args_dict, TR_KEY_metainfo) == nullptr);
@ -1040,41 +1040,22 @@ void Session::addTorrent(AddData add_me, tr_variant* args_dict, bool trash_origi
}); });
q->add( q->add(
[this, add_me, trash_original](RpcResponse const& r) [this, add_me](RpcResponse const& r)
{ {
bool session_has_torrent = false;
if (tr_variant* dup = nullptr; tr_variantDictFindDict(r.args.get(), TR_KEY_torrent_added, &dup)) if (tr_variant* dup = nullptr; tr_variantDictFindDict(r.args.get(), TR_KEY_torrent_added, &dup))
{ {
session_has_torrent = true; add_me.disposeSourceFile();
} }
else if (tr_variantDictFindDict(r.args.get(), TR_KEY_torrent_duplicate, &dup)) else if (tr_variantDictFindDict(r.args.get(), TR_KEY_torrent_duplicate, &dup))
{ {
session_has_torrent = true; add_me.disposeSourceFile();
auto const hash = dictFind<QString>(dup, TR_KEY_hashString); if (auto const hash = dictFind<QString>(dup, TR_KEY_hashString); hash)
if (hash)
{ {
duplicates_.try_emplace(add_me.readableShortName(), *hash); duplicates_.try_emplace(add_me.readableShortName(), *hash);
duplicates_timer_.start(1000); duplicates_timer_.start(1000);
} }
} }
if (auto const& filename = add_me.filename;
session_has_torrent && !filename.isEmpty() && add_me.type == AddData::FILENAME)
{
auto file = QFile{ filename };
if (trash_original)
{
file.setPermissions(QFile::ReadOwner | QFile::WriteOwner);
file.remove();
}
else
{
file.rename(QStringLiteral("%1.added").arg(filename));
}
}
}); });
q->run(); q->run();
@ -1115,8 +1096,7 @@ void Session::addTorrent(AddData add_me)
{ {
tr_variant args; tr_variant args;
tr_variantInitDict(&args, 3); tr_variantInitDict(&args, 3);
addTorrent(std::move(add_me), &args);
addTorrent(std::move(add_me), &args, prefs_.getBool(Prefs::TRASH_ORIGINAL));
} }
void Session::addNewlyCreatedTorrent(QString const& filename, QString const& local_path) void Session::addNewlyCreatedTorrent(QString const& filename, QString const& local_path)

View File

@ -93,7 +93,7 @@ public:
void torrentSetLocation(torrent_ids_t const& torrent_ids, QString const& path, bool do_move); void torrentSetLocation(torrent_ids_t const& torrent_ids, QString const& path, bool do_move);
void torrentRenamePath(torrent_ids_t const& torrent_ids, QString const& oldpath, QString const& newname); void torrentRenamePath(torrent_ids_t const& torrent_ids, QString const& oldpath, QString const& newname);
void addTorrent(AddData add_me, tr_variant* args_dict, bool trash_original); void addTorrent(AddData add_me, tr_variant* args_dict);
void initTorrents(torrent_ids_t const& ids = {}); void initTorrents(torrent_ids_t const& ids = {});
void pauseTorrents(torrent_ids_t const& torrent_ids = {}); void pauseTorrents(torrent_ids_t const& torrent_ids = {});
void startTorrents(torrent_ids_t const& torrent_ids = {}); void startTorrents(torrent_ids_t const& torrent_ids = {});