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();
}
}
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
{
public:
// what to do with the source file after adding the torrent
enum class FilenameDisposal
{
NoAction,
Delete,
Rename
};
enum
{
NONE,
@ -36,6 +44,18 @@ public:
QString readableName() 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)
{
if (auto ret = AddData{ str }; ret.type != NONE)
@ -51,4 +71,7 @@ public:
QString filename;
QString magnet;
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::torrentsRemoved, model_.get(), &TorrentModel::removeTorrents);
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
for (auto const key : { Prefs::DIR_WATCH })
@ -345,9 +345,10 @@ Application::Application(int& argc, char** argv)
dialog->show();
}
// torrent files passed in on the command line
for (QString const& filename : filenames)
{
addTorrent(filename);
addTorrent(AddData{ filename });
}
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)
{
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))
{
session_->addTorrent(addme);

View File

@ -16,6 +16,7 @@
#include <libtransmission/tr-macros.h>
#include "AddData.h"
#include "FaviconCache.h"
#include "Typedefs.h"
#include "Utils.h" // std::hash<QString>
@ -47,8 +48,8 @@ public:
FaviconCache& faviconCache();
public slots:
void addTorrent(AddData const&) const;
void addTorrent(QString const&) const;
void addTorrent(AddData) const;
void addWatchdirTorrent(QString const& filename) const;
private slots:
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)
{
auto const* const b = file_dialog->findChild<QCheckBox const*>(show_options_checkbox_name_);
if (b != nullptr)
if (auto const* const b = file_dialog->findChild<QCheckBox const*>(show_options_checkbox_name_); b != nullptr)
{
show_options = b->isChecked();
}
@ -1326,7 +1324,7 @@ void MainWindow::addTorrents(QStringList const& 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();
}
trApp->addTorrent(AddData(key));
trApp->addTorrent(AddData{ key });
}
}
}
@ -1626,7 +1624,7 @@ bool MainWindow::event(QEvent* e)
if (!clipboard_processed_keys_.contains(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();
}

View File

@ -992,7 +992,7 @@ void Session::setBlocklistSize(int64_t 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_metainfo) == nullptr);
@ -1040,41 +1040,22 @@ void Session::addTorrent(AddData add_me, tr_variant* args_dict, bool trash_origi
});
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))
{
session_has_torrent = true;
add_me.disposeSourceFile();
}
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 (hash)
if (auto const hash = dictFind<QString>(dup, TR_KEY_hashString); hash)
{
duplicates_.try_emplace(add_me.readableShortName(), *hash);
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();
@ -1115,8 +1096,7 @@ void Session::addTorrent(AddData add_me)
{
tr_variant args;
tr_variantInitDict(&args, 3);
addTorrent(std::move(add_me), &args, prefs_.getBool(Prefs::TRASH_ORIGINAL));
addTorrent(std::move(add_me), &args);
}
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 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 pauseTorrents(torrent_ids_t const& torrent_ids = {});
void startTorrents(torrent_ids_t const& torrent_ids = {});