mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2025-12-23 08:48:07 -06:00
Merge pull request #15536 from glassez/expected
Don't use output parameters for error handling
This commit is contained in:
@@ -69,7 +69,6 @@
|
||||
#include <QUuid>
|
||||
|
||||
#include "base/algorithm.h"
|
||||
#include "base/exceptions.h"
|
||||
#include "base/global.h"
|
||||
#include "base/logger.h"
|
||||
#include "base/net/downloadmanager.h"
|
||||
@@ -1698,7 +1697,7 @@ void Session::handleDownloadFinished(const Net::DownloadResult &result)
|
||||
{
|
||||
case Net::DownloadStatus::Success:
|
||||
emit downloadFromUrlFinished(result.url);
|
||||
addTorrent(TorrentInfo::load(result.data), m_downloadedTorrents.take(result.url));
|
||||
addTorrent(TorrentInfo::load(result.data).value_or(TorrentInfo()), m_downloadedTorrents.take(result.url));
|
||||
break;
|
||||
case Net::DownloadStatus::RedirectedToMagnet:
|
||||
emit downloadFromUrlFinished(result.url);
|
||||
@@ -2028,7 +2027,7 @@ bool Session::addTorrent(const QString &source, const AddTorrentParams ¶ms)
|
||||
return addTorrent(magnetUri, params);
|
||||
|
||||
TorrentFileGuard guard {source};
|
||||
if (addTorrent(TorrentInfo::loadFromFile(source), params))
|
||||
if (addTorrent(TorrentInfo::loadFromFile(source).value_or(TorrentInfo()), params))
|
||||
{
|
||||
guard.markAsAddedToSession();
|
||||
return true;
|
||||
@@ -2317,14 +2316,11 @@ void Session::exportTorrentFile(const TorrentInfo &torrentInfo, const QString &f
|
||||
newTorrentPath = exportDir.absoluteFilePath(torrentExportFilename);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
torrentInfo.saveToFile(newTorrentPath);
|
||||
}
|
||||
catch (const RuntimeError &err)
|
||||
const nonstd::expected<void, QString> result = torrentInfo.saveToFile(newTorrentPath);
|
||||
if (!result)
|
||||
{
|
||||
LogMsg(tr("Couldn't export torrent metadata file '%1'. Reason: %2.")
|
||||
.arg(newTorrentPath, err.message()), Log::WARNING);
|
||||
.arg(newTorrentPath, result.error()), Log::WARNING);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3938,8 +3934,7 @@ void Session::handleTorrentFinished(TorrentImpl *const torrent)
|
||||
qDebug("Found possible recursive torrent download.");
|
||||
const QString torrentFullpath = torrent->savePath(true) + '/' + torrentRelpath;
|
||||
qDebug("Full subtorrent path is %s", qUtf8Printable(torrentFullpath));
|
||||
TorrentInfo torrentInfo = TorrentInfo::loadFromFile(torrentFullpath);
|
||||
if (torrentInfo.isValid())
|
||||
if (TorrentInfo::loadFromFile(torrentFullpath))
|
||||
{
|
||||
qDebug("emitting recursiveTorrentDownloadPossible()");
|
||||
emit recursiveTorrentDownloadPossible(torrent);
|
||||
@@ -4167,7 +4162,7 @@ void Session::recursiveTorrentDownload(const TorrentID &id)
|
||||
AddTorrentParams params;
|
||||
// Passing the save path along to the sub torrent file
|
||||
params.savePath = torrent->savePath();
|
||||
addTorrent(TorrentInfo::loadFromFile(torrentFullpath), params);
|
||||
addTorrent(TorrentInfo::loadFromFile(torrentFullpath).value_or(TorrentInfo()), params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
#include <QUrl>
|
||||
#include <QVector>
|
||||
|
||||
#include "base/exceptions.h"
|
||||
#include "base/global.h"
|
||||
#include "base/utils/fs.h"
|
||||
#include "base/utils/io.h"
|
||||
@@ -106,7 +105,7 @@ TorrentInfo &TorrentInfo::operator=(const TorrentInfo &other)
|
||||
return *this;
|
||||
}
|
||||
|
||||
TorrentInfo TorrentInfo::load(const QByteArray &data, QString *error) noexcept
|
||||
nonstd::expected<TorrentInfo, QString> TorrentInfo::load(const QByteArray &data) noexcept
|
||||
{
|
||||
// 2-step construction to overcome default limits of `depth_limit` & `token_limit` which are
|
||||
// used in `torrent_info()` constructor
|
||||
@@ -117,42 +116,23 @@ TorrentInfo TorrentInfo::load(const QByteArray &data, QString *error) noexcept
|
||||
const lt::bdecode_node node = lt::bdecode(data, ec
|
||||
, nullptr, depthLimit, tokenLimit);
|
||||
if (ec)
|
||||
{
|
||||
if (error)
|
||||
*error = QString::fromStdString(ec.message());
|
||||
return TorrentInfo();
|
||||
}
|
||||
return nonstd::make_unexpected(QString::fromStdString(ec.message()));
|
||||
|
||||
TorrentInfo info {std::shared_ptr<lt::torrent_info>(new lt::torrent_info(node, ec))};
|
||||
if (ec)
|
||||
{
|
||||
if (error)
|
||||
*error = QString::fromStdString(ec.message());
|
||||
return TorrentInfo();
|
||||
}
|
||||
return nonstd::make_unexpected(QString::fromStdString(ec.message()));
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
TorrentInfo TorrentInfo::loadFromFile(const QString &path, QString *error) noexcept
|
||||
nonstd::expected<TorrentInfo, QString> TorrentInfo::loadFromFile(const QString &path) noexcept
|
||||
{
|
||||
if (error)
|
||||
error->clear();
|
||||
|
||||
QFile file {path};
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
if (error)
|
||||
*error = file.errorString();
|
||||
return TorrentInfo();
|
||||
}
|
||||
return nonstd::make_unexpected(file.errorString());
|
||||
|
||||
if (file.size() > MAX_TORRENT_SIZE)
|
||||
{
|
||||
if (error)
|
||||
*error = tr("File size exceeds max limit %1").arg(Utils::Misc::friendlyUnit(MAX_TORRENT_SIZE));
|
||||
return TorrentInfo();
|
||||
}
|
||||
return nonstd::make_unexpected(tr("File size exceeds max limit %1").arg(Utils::Misc::friendlyUnit(MAX_TORRENT_SIZE)));
|
||||
|
||||
QByteArray data;
|
||||
try
|
||||
@@ -161,26 +141,21 @@ TorrentInfo TorrentInfo::loadFromFile(const QString &path, QString *error) noexc
|
||||
}
|
||||
catch (const std::bad_alloc &e)
|
||||
{
|
||||
if (error)
|
||||
*error = tr("Torrent file read error: %1").arg(e.what());
|
||||
return TorrentInfo();
|
||||
return nonstd::make_unexpected(tr("Torrent file read error: %1").arg(e.what()));
|
||||
}
|
||||
|
||||
if (data.size() != file.size())
|
||||
{
|
||||
if (error)
|
||||
*error = tr("Torrent file read error: size mismatch");
|
||||
return TorrentInfo();
|
||||
}
|
||||
return nonstd::make_unexpected(tr("Torrent file read error: size mismatch"));
|
||||
|
||||
file.close();
|
||||
|
||||
return load(data, error);
|
||||
return load(data);
|
||||
}
|
||||
|
||||
void TorrentInfo::saveToFile(const QString &path) const
|
||||
nonstd::expected<void, QString> TorrentInfo::saveToFile(const QString &path) const
|
||||
{
|
||||
if (!isValid())
|
||||
throw RuntimeError {tr("Invalid metadata")};
|
||||
return nonstd::make_unexpected(tr("Invalid metadata"));
|
||||
|
||||
try
|
||||
{
|
||||
@@ -188,12 +163,14 @@ void TorrentInfo::saveToFile(const QString &path) const
|
||||
const lt::entry torrentEntry = torrentCreator.generate();
|
||||
const nonstd::expected<void, QString> result = Utils::IO::saveToFile(path, torrentEntry);
|
||||
if (!result)
|
||||
throw RuntimeError(result.error());
|
||||
return result.get_unexpected();
|
||||
}
|
||||
catch (const lt::system_error &err)
|
||||
{
|
||||
throw RuntimeError(QString::fromLocal8Bit(err.what()));
|
||||
return nonstd::make_unexpected(QString::fromLocal8Bit(err.what()));
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
bool TorrentInfo::isValid() const
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <QCoreApplication>
|
||||
#include <QtContainerFwd>
|
||||
|
||||
#include "base/3rdparty/expected.hpp"
|
||||
#include "base/indexrange.h"
|
||||
#include "abstractfilestorage.h"
|
||||
#include "torrentcontentlayout.h"
|
||||
@@ -55,9 +56,9 @@ namespace BitTorrent
|
||||
explicit TorrentInfo(std::shared_ptr<const lt::torrent_info> nativeInfo = {});
|
||||
TorrentInfo(const TorrentInfo &other);
|
||||
|
||||
static TorrentInfo load(const QByteArray &data, QString *error = nullptr) noexcept;
|
||||
static TorrentInfo loadFromFile(const QString &path, QString *error = nullptr) noexcept;
|
||||
void saveToFile(const QString &path) const;
|
||||
static nonstd::expected<TorrentInfo, QString> load(const QByteArray &data) noexcept;
|
||||
static nonstd::expected<TorrentInfo, QString> loadFromFile(const QString &path) noexcept;
|
||||
nonstd::expected<void, QString> saveToFile(const QString &path) const;
|
||||
|
||||
TorrentInfo &operator=(const TorrentInfo &other);
|
||||
|
||||
|
||||
@@ -142,67 +142,59 @@ Session *Session::instance()
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
bool Session::addFolder(const QString &path, QString *error)
|
||||
nonstd::expected<void, QString> Session::addFolder(const QString &path)
|
||||
{
|
||||
Folder *destFolder = prepareItemDest(path, error);
|
||||
if (!destFolder)
|
||||
return false;
|
||||
const nonstd::expected<Folder *, QString> result = prepareItemDest(path);
|
||||
if (!result)
|
||||
return result.get_unexpected();
|
||||
|
||||
const auto destFolder = result.value();
|
||||
addItem(new Folder(path), destFolder);
|
||||
store();
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
|
||||
bool Session::addFeed(const QString &url, const QString &path, QString *error)
|
||||
nonstd::expected<void, QString> Session::addFeed(const QString &url, const QString &path)
|
||||
{
|
||||
if (m_feedsByURL.contains(url))
|
||||
{
|
||||
if (error)
|
||||
*error = tr("RSS feed with given URL already exists: %1.").arg(url);
|
||||
return false;
|
||||
}
|
||||
return nonstd::make_unexpected(tr("RSS feed with given URL already exists: %1.").arg(url));
|
||||
|
||||
Folder *destFolder = prepareItemDest(path, error);
|
||||
if (!destFolder)
|
||||
return false;
|
||||
const nonstd::expected<Folder *, QString> result = prepareItemDest(path);
|
||||
if (!result)
|
||||
return result.get_unexpected();
|
||||
|
||||
const auto destFolder = result.value();
|
||||
addItem(new Feed(generateUID(), url, path, this), destFolder);
|
||||
store();
|
||||
if (m_processingEnabled)
|
||||
feedByURL(url)->refresh();
|
||||
return true;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
bool Session::moveItem(const QString &itemPath, const QString &destPath, QString *error)
|
||||
nonstd::expected<void, QString> Session::moveItem(const QString &itemPath, const QString &destPath)
|
||||
{
|
||||
if (itemPath.isEmpty())
|
||||
{
|
||||
if (error)
|
||||
*error = tr("Cannot move root folder.");
|
||||
return false;
|
||||
}
|
||||
return nonstd::make_unexpected(tr("Cannot move root folder."));
|
||||
|
||||
auto item = m_itemsByPath.value(itemPath);
|
||||
if (!item)
|
||||
{
|
||||
if (error)
|
||||
*error = tr("Item doesn't exist: %1.").arg(itemPath);
|
||||
return false;
|
||||
}
|
||||
return nonstd::make_unexpected(tr("Item doesn't exist: %1.").arg(itemPath));
|
||||
|
||||
return moveItem(item, destPath, error);
|
||||
return moveItem(item, destPath);
|
||||
}
|
||||
|
||||
bool Session::moveItem(Item *item, const QString &destPath, QString *error)
|
||||
nonstd::expected<void, QString> Session::moveItem(Item *item, const QString &destPath)
|
||||
{
|
||||
Q_ASSERT(item);
|
||||
Q_ASSERT(item != rootFolder());
|
||||
|
||||
Folder *destFolder = prepareItemDest(destPath, error);
|
||||
if (!destFolder)
|
||||
return false;
|
||||
const nonstd::expected<Folder *, QString> result = prepareItemDest(destPath);
|
||||
if (!result)
|
||||
return result.get_unexpected();
|
||||
|
||||
auto srcFolder = static_cast<Folder *>(m_itemsByPath.value(Item::parentPath(item->path())));
|
||||
const auto destFolder = result.value();
|
||||
if (srcFolder != destFolder)
|
||||
{
|
||||
srcFolder->removeItem(item);
|
||||
@@ -211,25 +203,17 @@ bool Session::moveItem(Item *item, const QString &destPath, QString *error)
|
||||
m_itemsByPath.insert(destPath, m_itemsByPath.take(item->path()));
|
||||
item->setPath(destPath);
|
||||
store();
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
|
||||
bool Session::removeItem(const QString &itemPath, QString *error)
|
||||
nonstd::expected<void, QString> Session::removeItem(const QString &itemPath)
|
||||
{
|
||||
if (itemPath.isEmpty())
|
||||
{
|
||||
if (error)
|
||||
*error = tr("Cannot delete root folder.");
|
||||
return false;
|
||||
}
|
||||
return nonstd::make_unexpected(tr("Cannot delete root folder."));
|
||||
|
||||
auto item = m_itemsByPath.value(itemPath);
|
||||
auto *item = m_itemsByPath.value(itemPath);
|
||||
if (!item)
|
||||
{
|
||||
if (error)
|
||||
*error = tr("Item doesn't exist: %1.").arg(itemPath);
|
||||
return false;
|
||||
}
|
||||
return nonstd::make_unexpected(tr("Item doesn't exist: %1.").arg(itemPath));
|
||||
|
||||
emit itemAboutToBeRemoved(item);
|
||||
item->cleanup();
|
||||
@@ -238,7 +222,7 @@ bool Session::removeItem(const QString &itemPath, QString *error)
|
||||
folder->removeItem(item);
|
||||
delete item;
|
||||
store();
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
|
||||
QList<Item *> Session::items() const
|
||||
@@ -395,30 +379,18 @@ void Session::store()
|
||||
m_confFileStorage->store(FeedsFileName, QJsonDocument(rootFolder()->toJsonValue().toObject()).toJson());
|
||||
}
|
||||
|
||||
Folder *Session::prepareItemDest(const QString &path, QString *error)
|
||||
nonstd::expected<Folder *, QString> Session::prepareItemDest(const QString &path)
|
||||
{
|
||||
if (!Item::isValidPath(path))
|
||||
{
|
||||
if (error)
|
||||
*error = tr("Incorrect RSS Item path: %1.").arg(path);
|
||||
return nullptr;
|
||||
}
|
||||
return nonstd::make_unexpected(tr("Incorrect RSS Item path: %1.").arg(path));
|
||||
|
||||
if (m_itemsByPath.contains(path))
|
||||
{
|
||||
if (error)
|
||||
*error = tr("RSS item with given path already exists: %1.").arg(path);
|
||||
return nullptr;
|
||||
}
|
||||
return nonstd::make_unexpected(tr("RSS item with given path already exists: %1.").arg(path));
|
||||
|
||||
const QString destFolderPath = Item::parentPath(path);
|
||||
auto destFolder = qobject_cast<Folder *>(m_itemsByPath.value(destFolderPath));
|
||||
const auto destFolder = qobject_cast<Folder *>(m_itemsByPath.value(destFolderPath));
|
||||
if (!destFolder)
|
||||
{
|
||||
if (error)
|
||||
*error = tr("Parent folder doesn't exist: %1.").arg(destFolderPath);
|
||||
return nullptr;
|
||||
}
|
||||
return nonstd::make_unexpected(tr("Parent folder doesn't exist: %1.").arg(destFolderPath));
|
||||
|
||||
return destFolder;
|
||||
}
|
||||
|
||||
@@ -73,6 +73,8 @@
|
||||
#include <QPointer>
|
||||
#include <QTimer>
|
||||
|
||||
#include "base/3rdparty/expected.hpp"
|
||||
|
||||
class QThread;
|
||||
|
||||
class Application;
|
||||
@@ -110,12 +112,11 @@ namespace RSS
|
||||
int refreshInterval() const;
|
||||
void setRefreshInterval(int refreshInterval);
|
||||
|
||||
bool addFolder(const QString &path, QString *error = nullptr);
|
||||
bool addFeed(const QString &url, const QString &path, QString *error = nullptr);
|
||||
bool moveItem(const QString &itemPath, const QString &destPath
|
||||
, QString *error = nullptr);
|
||||
bool moveItem(Item *item, const QString &destPath, QString *error = nullptr);
|
||||
bool removeItem(const QString &itemPath, QString *error = nullptr);
|
||||
nonstd::expected<void, QString> addFolder(const QString &path);
|
||||
nonstd::expected<void, QString> addFeed(const QString &url, const QString &path);
|
||||
nonstd::expected<void, QString> moveItem(const QString &itemPath, const QString &destPath);
|
||||
nonstd::expected<void, QString> moveItem(Item *item, const QString &destPath);
|
||||
nonstd::expected<void, QString> removeItem(const QString &itemPath);
|
||||
|
||||
QList<Item *> items() const;
|
||||
Item *itemByPath(const QString &path) const;
|
||||
@@ -146,7 +147,7 @@ namespace RSS
|
||||
void loadFolder(const QJsonObject &jsonObj, Folder *folder);
|
||||
void loadLegacy();
|
||||
void store();
|
||||
Folder *prepareItemDest(const QString &path, QString *error);
|
||||
nonstd::expected<Folder *, QString> prepareItemDest(const QString &path);
|
||||
Folder *addSubfolder(const QString &name, Folder *parentFolder);
|
||||
Feed *addFeedToFolder(const QUuid &uid, const QString &url, const QString &name, Folder *parentFolder);
|
||||
void addItem(Item *item, Folder *destFolder);
|
||||
|
||||
@@ -526,10 +526,10 @@ void TorrentFilesWatcher::Worker::processFolder(const QString &path, const QStri
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto torrentInfo = BitTorrent::TorrentInfo::loadFromFile(filePath);
|
||||
if (torrentInfo.isValid())
|
||||
const nonstd::expected<BitTorrent::TorrentInfo, QString> result = BitTorrent::TorrentInfo::loadFromFile(filePath);
|
||||
if (result)
|
||||
{
|
||||
emit torrentFound(torrentInfo, addTorrentParams);
|
||||
emit torrentFound(result.value(), addTorrentParams);
|
||||
Utils::Fs::forceRemove(filePath);
|
||||
}
|
||||
else
|
||||
@@ -567,8 +567,8 @@ void TorrentFilesWatcher::Worker::processFailedTorrents()
|
||||
if (!QFile::exists(torrentPath))
|
||||
return true;
|
||||
|
||||
const auto torrentInfo = BitTorrent::TorrentInfo::loadFromFile(torrentPath);
|
||||
if (torrentInfo.isValid())
|
||||
const nonstd::expected<BitTorrent::TorrentInfo, QString> result = BitTorrent::TorrentInfo::loadFromFile(torrentPath);
|
||||
if (result)
|
||||
{
|
||||
BitTorrent::AddTorrentParams addTorrentParams = options.addTorrentParams;
|
||||
const QString exactDirPath = QFileInfo(torrentPath).canonicalPath();
|
||||
@@ -578,7 +578,7 @@ void TorrentFilesWatcher::Worker::processFailedTorrents()
|
||||
addTorrentParams.savePath = QDir(addTorrentParams.savePath).filePath(subdirPath);
|
||||
}
|
||||
|
||||
emit torrentFound(torrentInfo, addTorrentParams);
|
||||
emit torrentFound(result.value(), addTorrentParams);
|
||||
Utils::Fs::forceRemove(torrentPath);
|
||||
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user