Implement class for handling filesystem paths

PR #15915.
This commit is contained in:
Vladimir Golovnev
2022-02-08 06:03:48 +03:00
committed by GitHub
parent facfa26eed
commit dd1bd8ad10
131 changed files with 2252 additions and 1868 deletions

View File

@@ -45,7 +45,6 @@
#include <QAtomicInt>
#include <QDebug>
#include <QDir>
#include <QLibraryInfo>
#include <QProcess>
@@ -80,6 +79,7 @@
#include "base/torrentfileswatcher.h"
#include "base/utils/compare.h"
#include "base/utils/fs.h"
#include "base/path.h"
#include "base/utils/misc.h"
#include "base/version.h"
#include "applicationinstancemanager.h"
@@ -105,7 +105,7 @@ namespace
const QString LOG_FOLDER = QStringLiteral("logs");
const QChar PARAMS_SEPARATOR = QLatin1Char('|');
const QString DEFAULT_PORTABLE_MODE_PROFILE_DIR = QStringLiteral("profile");
const Path DEFAULT_PORTABLE_MODE_PROFILE_DIR {QStringLiteral("profile")};
const int MIN_FILELOG_SIZE = 1024; // 1KiB
const int MAX_FILELOG_SIZE = 1000 * 1024 * 1024; // 1000MiB
@@ -143,16 +143,16 @@ Application::Application(int &argc, char **argv)
QPixmapCache::setCacheLimit(PIXMAP_CACHE_SIZE);
#endif
const bool portableModeEnabled = m_commandLineArgs.profileDir.isEmpty()
&& QDir(QCoreApplication::applicationDirPath()).exists(DEFAULT_PORTABLE_MODE_PROFILE_DIR);
const auto portableProfilePath = Path(QCoreApplication::applicationDirPath()) / DEFAULT_PORTABLE_MODE_PROFILE_DIR;
const bool portableModeEnabled = m_commandLineArgs.profileDir.isEmpty() && portableProfilePath.exists();
const QString profileDir = portableModeEnabled
? QDir(QCoreApplication::applicationDirPath()).absoluteFilePath(DEFAULT_PORTABLE_MODE_PROFILE_DIR)
const Path profileDir = portableModeEnabled
? portableProfilePath
: m_commandLineArgs.profileDir;
Profile::initInstance(profileDir, m_commandLineArgs.configurationName,
(m_commandLineArgs.relativeFastresumePaths || portableModeEnabled));
m_instanceManager = new ApplicationInstanceManager {Profile::instance()->location(SpecialFolder::Config), this};
m_instanceManager = new ApplicationInstanceManager(Profile::instance()->location(SpecialFolder::Config), this);
Logger::initInstance();
SettingsStorage::initInstance();
@@ -175,13 +175,13 @@ Application::Application(int &argc, char **argv)
Logger::instance()->addMessage(tr("qBittorrent %1 started", "qBittorrent v3.2.0alpha started").arg(QBT_VERSION));
if (portableModeEnabled)
{
Logger::instance()->addMessage(tr("Running in portable mode. Auto detected profile folder at: %1").arg(profileDir));
Logger::instance()->addMessage(tr("Running in portable mode. Auto detected profile folder at: %1").arg(profileDir.toString()));
if (m_commandLineArgs.relativeFastresumePaths)
Logger::instance()->addMessage(tr("Redundant command line flag detected: \"%1\". Portable mode implies relative fastresume.").arg("--relative-fastresume"), Log::WARNING); // to avoid translating the `--relative-fastresume` string
}
else
{
Logger::instance()->addMessage(tr("Using config directory: %1").arg(Profile::instance()->location(SpecialFolder::Config)));
Logger::instance()->addMessage(tr("Using config directory: %1").arg(Profile::instance()->location(SpecialFolder::Config).toString()));
}
}
@@ -218,12 +218,12 @@ void Application::setFileLoggerEnabled(const bool value)
m_storeFileLoggerEnabled = value;
}
QString Application::fileLoggerPath() const
Path Application::fileLoggerPath() const
{
return m_storeFileLoggerPath.get(QDir(specialFolderLocation(SpecialFolder::Data)).absoluteFilePath(LOG_FOLDER));
return m_storeFileLoggerPath.get(specialFolderLocation(SpecialFolder::Data) / Path(LOG_FOLDER));
}
void Application::setFileLoggerPath(const QString &path)
void Application::setFileLoggerPath(const Path &path)
{
if (m_fileLogger)
m_fileLogger->changePath(path);
@@ -327,16 +327,16 @@ void Application::runExternalProgram(const BitTorrent::Torrent *torrent) const
break;
case u'D':
#if defined(Q_OS_WIN)
program.replace(i, 2, chopPathSep(Utils::Fs::toNativePath(torrent->savePath())));
program.replace(i, 2, chopPathSep(torrent->savePath().toString()));
#else
program.replace(i, 2, Utils::Fs::toNativePath(torrent->savePath()));
program.replace(i, 2, torrent->savePath().toString());
#endif
break;
case u'F':
#if defined(Q_OS_WIN)
program.replace(i, 2, chopPathSep(Utils::Fs::toNativePath(torrent->contentPath())));
program.replace(i, 2, chopPathSep(torrent->contentPath().toString()));
#else
program.replace(i, 2, Utils::Fs::toNativePath(torrent->contentPath()));
program.replace(i, 2, torrent->contentPath().toString());
#endif
break;
case u'G':
@@ -359,9 +359,9 @@ void Application::runExternalProgram(const BitTorrent::Torrent *torrent) const
break;
case u'R':
#if defined(Q_OS_WIN)
program.replace(i, 2, chopPathSep(Utils::Fs::toNativePath(torrent->rootPath())));
program.replace(i, 2, chopPathSep(torrent->rootPath().toString()));
#else
program.replace(i, 2, Utils::Fs::toNativePath(torrent->rootPath()));
program.replace(i, 2, torrent->rootPath().toString());
#endif
break;
case u'T':
@@ -439,7 +439,7 @@ void Application::sendNotificationEmail(const BitTorrent::Torrent *torrent)
// Prepare mail content
const QString content = tr("Torrent name: %1").arg(torrent->name()) + '\n'
+ tr("Torrent size: %1").arg(Utils::Misc::friendlyUnit(torrent->wantedSize())) + '\n'
+ tr("Save path: %1").arg(torrent->savePath()) + "\n\n"
+ tr("Save path: %1").arg(torrent->savePath().toString()) + "\n\n"
+ tr("The torrent was downloaded in %1.", "The torrent was downloaded in 1 hour and 20 seconds")
.arg(Utils::Misc::userFriendlyDuration(torrent->activeTime())) + "\n\n\n"
+ tr("Thank you for using qBittorrent.") + '\n';
@@ -545,7 +545,7 @@ void Application::processParams(const QStringList &params)
if (param.startsWith(QLatin1String("@savePath=")))
{
torrentParams.savePath = param.mid(10);
torrentParams.savePath = Path(param.mid(10));
continue;
}
@@ -821,7 +821,7 @@ void Application::cleanup()
Logger::freeInstance();
IconProvider::freeInstance();
SearchPluginManager::freeInstance();
Utils::Fs::removeDirRecursive(Utils::Fs::tempPath());
Utils::Fs::removeDirRecursively(Utils::Fs::tempPath());
#ifndef DISABLE_GUI
if (m_window)

View File

@@ -47,6 +47,7 @@ class QSessionManager;
using BaseApplication = QCoreApplication;
#endif // DISABLE_GUI
#include "base/path.h"
#include "base/settingvalue.h"
#include "base/types.h"
#include "cmdoptions.h"
@@ -91,8 +92,8 @@ public:
// FileLogger properties
bool isFileLoggerEnabled() const;
void setFileLoggerEnabled(bool value);
QString fileLoggerPath() const;
void setFileLoggerPath(const QString &path);
Path fileLoggerPath() const;
void setFileLoggerPath(const Path &path);
bool isFileLoggerBackup() const;
void setFileLoggerBackup(bool value);
bool isFileLoggerDeleteOld() const;
@@ -152,5 +153,5 @@ private:
SettingValue<int> m_storeFileLoggerMaxSize;
SettingValue<int> m_storeFileLoggerAge;
SettingValue<int> m_storeFileLoggerAgeType;
SettingValue<QString> m_storeFileLoggerPath;
SettingValue<Path> m_storeFileLoggerPath;
};

View File

@@ -37,18 +37,19 @@
#include <QSharedMemory>
#endif
#include "base/path.h"
#include "qtlocalpeer/qtlocalpeer.h"
ApplicationInstanceManager::ApplicationInstanceManager(const QString &instancePath, QObject *parent)
ApplicationInstanceManager::ApplicationInstanceManager(const Path &instancePath, QObject *parent)
: QObject {parent}
, m_peer {new QtLocalPeer {instancePath, this}}
, m_peer {new QtLocalPeer(instancePath.data(), this)}
, m_isFirstInstance {!m_peer->isClient()}
{
connect(m_peer, &QtLocalPeer::messageReceived, this, &ApplicationInstanceManager::messageReceived);
#ifdef Q_OS_WIN
const QString sharedMemoryKey = instancePath + QLatin1String {"/shared-memory"};
auto sharedMem = new QSharedMemory {sharedMemoryKey, this};
const QString sharedMemoryKey = instancePath.data() + QLatin1String("/shared-memory");
auto sharedMem = new QSharedMemory(sharedMemoryKey, this);
if (m_isFirstInstance)
{
// First instance creates shared memory and store PID

View File

@@ -30,6 +30,8 @@
#include <QObject>
#include "base/pathfwd.h"
class QtLocalPeer;
class ApplicationInstanceManager final : public QObject
@@ -38,7 +40,7 @@ class ApplicationInstanceManager final : public QObject
Q_DISABLE_COPY_MOVE(ApplicationInstanceManager)
public:
explicit ApplicationInstanceManager(const QString &instancePath, QObject *parent = nullptr);
explicit ApplicationInstanceManager(const Path &instancePath, QObject *parent = nullptr);
bool isFirstInstance() const;

View File

@@ -372,7 +372,7 @@ QStringList QBtCommandLineParameters::paramList() const
// torrent paths or URLs.
if (!savePath.isEmpty())
result.append(QLatin1String("@savePath=") + savePath);
result.append(QLatin1String("@savePath=") + savePath.data());
if (addPaused.has_value())
result.append(*addPaused ? QLatin1String {"@addPaused=1"} : QLatin1String {"@addPaused=0"});
@@ -438,7 +438,7 @@ QBtCommandLineParameters parseCommandLine(const QStringList &args)
#endif
else if (arg == PROFILE_OPTION)
{
result.profileDir = PROFILE_OPTION.value(arg);
result.profileDir = Path(PROFILE_OPTION.value(arg));
}
else if (arg == RELATIVE_FASTRESUME)
{
@@ -450,7 +450,7 @@ QBtCommandLineParameters parseCommandLine(const QStringList &args)
}
else if (arg == SAVE_PATH_OPTION)
{
result.savePath = SAVE_PATH_OPTION.value(arg);
result.savePath = Path(SAVE_PATH_OPTION.value(arg));
}
else if (arg == PAUSED_OPTION)
{

View File

@@ -36,6 +36,7 @@
#include <QStringList>
#include "base/exceptions.h"
#include "base/path.h"
class QProcessEnvironment;
@@ -58,9 +59,9 @@ struct QBtCommandLineParameters
std::optional<bool> addPaused;
std::optional<bool> skipDialog;
QStringList torrents;
QString profileDir;
Path profileDir;
QString configurationName;
QString savePath;
Path savePath;
QString category;
QString unknownParameter;

View File

@@ -44,7 +44,9 @@ namespace
const std::chrono::seconds FLUSH_INTERVAL {2};
}
FileLogger::FileLogger(const QString &path, const bool backup, const int maxSize, const bool deleteOld, const int age, const FileLogAgeType ageType)
FileLogger::FileLogger(const Path &path, const bool backup
, const int maxSize, const bool deleteOld, const int age
, const FileLogAgeType ageType)
: m_backup(backup)
, m_maxSize(maxSize)
{
@@ -68,26 +70,25 @@ FileLogger::~FileLogger()
closeLogFile();
}
void FileLogger::changePath(const QString &newPath)
void FileLogger::changePath(const Path &newPath)
{
const QDir dir(newPath);
dir.mkpath(newPath);
const QString tmpPath = dir.absoluteFilePath("qbittorrent.log");
// compare paths as strings to perform case sensitive comparison on all the platforms
if (newPath.data() == m_path.parentPath().data())
return;
if (tmpPath != m_path)
{
m_path = tmpPath;
closeLogFile();
closeLogFile();
m_logFile.setFileName(m_path);
openLogFile();
}
m_path = newPath / Path("qbittorrent.log");
m_logFile.setFileName(m_path.data());
Utils::Fs::mkpath(newPath);
openLogFile();
}
void FileLogger::deleteOld(const int age, const FileLogAgeType ageType)
{
const QDateTime date = QDateTime::currentDateTime();
const QDir dir(Utils::Fs::branchPath(m_path));
const QDir dir {m_path.parentPath().data()};
const QFileInfoList fileList = dir.entryInfoList(QStringList("qbittorrent.log.bak*")
, (QDir::Files | QDir::Writable), (QDir::Time | QDir::Reversed));
@@ -107,7 +108,7 @@ void FileLogger::deleteOld(const int age, const FileLogAgeType ageType)
}
if (modificationDate > date)
break;
Utils::Fs::forceRemove(file.absoluteFilePath());
Utils::Fs::removeFile(Path(file.absoluteFilePath()));
}
}
@@ -151,15 +152,15 @@ void FileLogger::addLogMessage(const Log::Msg &msg)
{
closeLogFile();
int counter = 0;
QString backupLogFilename = m_path + ".bak";
Path backupLogFilename = m_path + ".bak";
while (QFile::exists(backupLogFilename))
while (backupLogFilename.exists())
{
++counter;
backupLogFilename = m_path + ".bak" + QString::number(counter);
}
QFile::rename(m_path, backupLogFilename);
Utils::Fs::renameFile(m_path, backupLogFilename);
openLogFile();
}
else

View File

@@ -32,6 +32,8 @@
#include <QObject>
#include <QTimer>
#include "base/path.h"
namespace Log
{
struct Msg;
@@ -50,10 +52,10 @@ public:
YEARS
};
FileLogger(const QString &path, bool backup, int maxSize, bool deleteOld, int age, FileLogAgeType ageType);
FileLogger(const Path &path, bool backup, int maxSize, bool deleteOld, int age, FileLogAgeType ageType);
~FileLogger();
void changePath(const QString &newPath);
void changePath(const Path &newPath);
void deleteOld(int age, FileLogAgeType ageType);
void setBackup(bool value);
void setMaxSize(int value);
@@ -66,7 +68,7 @@ private:
void openLogFile();
void closeLogFile();
QString m_path;
Path m_path;
bool m_backup;
int m_maxSize;
QFile m_logFile;

View File

@@ -48,7 +48,7 @@ namespace
void exportWebUIHttpsFiles()
{
const auto migrate = [](const QString &oldKey, const QString &newKey, const QString &savePath)
const auto migrate = [](const QString &oldKey, const QString &newKey, const Path &savePath)
{
SettingsStorage *settingsStorage {SettingsStorage::instance()};
const auto oldData {settingsStorage->loadValue<QByteArray>(oldKey)};
@@ -61,24 +61,24 @@ namespace
const nonstd::expected<void, QString> result = Utils::IO::saveToFile(savePath, oldData);
if (!result)
{
LogMsg(errorMsgFormat.arg(savePath, result.error()) , Log::WARNING);
LogMsg(errorMsgFormat.arg(savePath.toString(), result.error()) , Log::WARNING);
return;
}
settingsStorage->storeValue(newKey, savePath);
settingsStorage->removeValue(oldKey);
LogMsg(QObject::tr("Migrated preferences: WebUI https, exported data to file: \"%1\"").arg(savePath)
LogMsg(QObject::tr("Migrated preferences: WebUI https, exported data to file: \"%1\"").arg(savePath.toString())
, Log::INFO);
};
const QString configPath {specialFolderLocation(SpecialFolder::Config)};
const Path configPath = specialFolderLocation(SpecialFolder::Config);
migrate(QLatin1String("Preferences/WebUI/HTTPS/Certificate")
, QLatin1String("Preferences/WebUI/HTTPS/CertificatePath")
, Utils::Fs::toNativePath(configPath + QLatin1String("/WebUICertificate.crt")));
, (configPath / Path("WebUICertificate.crt")));
migrate(QLatin1String("Preferences/WebUI/HTTPS/Key")
, QLatin1String("Preferences/WebUI/HTTPS/KeyPath")
, Utils::Fs::toNativePath(configPath + QLatin1String("/WebUIPrivateKey.pem")));
, (configPath / Path("WebUIPrivateKey.pem")));
}
void upgradeTorrentContentLayout()