mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-01-11 15:27:54 +00:00
Don't remove torrent contents parent folder, even it is empty. Closes #2244.
This commit is contained in:
parent
c75725e2d8
commit
4fcd107ff3
@ -813,11 +813,11 @@ bool Session::deleteTorrent(const QString &hash, bool deleteLocalFiles)
|
|||||||
|
|
||||||
// Remove it from session
|
// Remove it from session
|
||||||
if (deleteLocalFiles) {
|
if (deleteLocalFiles) {
|
||||||
QDir saveDir(torrent->actualSavePath());
|
QString tmp = torrent->filePath(0);
|
||||||
if ((saveDir != QDir(m_defaultSavePath)) && (saveDir != QDir(m_tempPath))) {
|
tmp.truncate(tmp.indexOf("/")); // get the torrent root directory name
|
||||||
m_savePathsToRemove[torrent->hash()] = saveDir.absolutePath();
|
if (!tmp.isEmpty())
|
||||||
qDebug() << "Save path to remove (async): " << saveDir.absolutePath();
|
m_savePathsToRemove[torrent->hash()] = torrent->actualSavePath() + tmp;
|
||||||
}
|
|
||||||
m_nativeSession->remove_torrent(torrent->nativeHandle(), libt::session::delete_files);
|
m_nativeSession->remove_torrent(torrent->nativeHandle(), libt::session::delete_files);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -2049,7 +2049,6 @@ void Session::handleAlert(libt::alert *a)
|
|||||||
handleMetadataReceivedAlert(static_cast<libt::metadata_received_alert*>(a));
|
handleMetadataReceivedAlert(static_cast<libt::metadata_received_alert*>(a));
|
||||||
dispatchTorrentAlert(a);
|
dispatchTorrentAlert(a);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case libt::state_update_alert::alert_type:
|
case libt::state_update_alert::alert_type:
|
||||||
handleStateUpdateAlert(static_cast<libt::state_update_alert*>(a));
|
handleStateUpdateAlert(static_cast<libt::state_update_alert*>(a));
|
||||||
break;
|
break;
|
||||||
@ -2065,6 +2064,9 @@ void Session::handleAlert(libt::alert *a)
|
|||||||
case libt::torrent_deleted_alert::alert_type:
|
case libt::torrent_deleted_alert::alert_type:
|
||||||
handleTorrentDeletedAlert(static_cast<libt::torrent_deleted_alert*>(a));
|
handleTorrentDeletedAlert(static_cast<libt::torrent_deleted_alert*>(a));
|
||||||
break;
|
break;
|
||||||
|
case libt::torrent_delete_failed_alert::alert_type:
|
||||||
|
handleTorrentDeleteFailedAlert(static_cast<libt::torrent_delete_failed_alert*>(a));
|
||||||
|
break;
|
||||||
case libt::portmap_error_alert::alert_type:
|
case libt::portmap_error_alert::alert_type:
|
||||||
handlePortmapWarningAlert(static_cast<libt::portmap_error_alert*>(a));
|
handlePortmapWarningAlert(static_cast<libt::portmap_error_alert*>(a));
|
||||||
break;
|
break;
|
||||||
@ -2178,13 +2180,16 @@ void Session::handleTorrentRemovedAlert(libtorrent::torrent_removed_alert *p)
|
|||||||
|
|
||||||
void Session::handleTorrentDeletedAlert(libt::torrent_deleted_alert *p)
|
void Session::handleTorrentDeletedAlert(libt::torrent_deleted_alert *p)
|
||||||
{
|
{
|
||||||
|
m_savePathsToRemove.remove(p->info_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::handleTorrentDeleteFailedAlert(libt::torrent_delete_failed_alert *p)
|
||||||
|
{
|
||||||
|
// libtorrent won't delete the directory if it contains files not listed in the torrent,
|
||||||
|
// so we remove the directory ourselves
|
||||||
if (m_savePathsToRemove.contains(p->info_hash)) {
|
if (m_savePathsToRemove.contains(p->info_hash)) {
|
||||||
qDebug("A torrent was deleted from the hard disk, attempting to remove the root folder too...");
|
QString path = m_savePathsToRemove.take(p->info_hash);
|
||||||
const QString dirpath = m_savePathsToRemove.take(p->info_hash);
|
Utils::Fs::smartRemoveEmptyFolderTree(path);
|
||||||
qDebug() << "Removing save path: " << dirpath << "...";
|
|
||||||
bool ok = Utils::Fs::smartRemoveEmptyFolderTree(dirpath);
|
|
||||||
Q_UNUSED(ok);
|
|
||||||
qDebug() << "Folder was removed: " << ok;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +61,7 @@ namespace libtorrent
|
|||||||
struct torrent_finished_alert;
|
struct torrent_finished_alert;
|
||||||
struct torrent_removed_alert;
|
struct torrent_removed_alert;
|
||||||
struct torrent_deleted_alert;
|
struct torrent_deleted_alert;
|
||||||
|
struct torrent_delete_failed_alert;
|
||||||
struct torrent_paused_alert;
|
struct torrent_paused_alert;
|
||||||
struct torrent_resumed_alert;
|
struct torrent_resumed_alert;
|
||||||
struct save_resume_data_alert;
|
struct save_resume_data_alert;
|
||||||
@ -305,6 +306,7 @@ namespace BitTorrent
|
|||||||
void handleFileErrorAlert(libtorrent::file_error_alert *p);
|
void handleFileErrorAlert(libtorrent::file_error_alert *p);
|
||||||
void handleTorrentRemovedAlert(libtorrent::torrent_removed_alert *p);
|
void handleTorrentRemovedAlert(libtorrent::torrent_removed_alert *p);
|
||||||
void handleTorrentDeletedAlert(libtorrent::torrent_deleted_alert *p);
|
void handleTorrentDeletedAlert(libtorrent::torrent_deleted_alert *p);
|
||||||
|
void handleTorrentDeleteFailedAlert(libtorrent::torrent_delete_failed_alert *p);
|
||||||
void handlePortmapWarningAlert(libtorrent::portmap_error_alert *p);
|
void handlePortmapWarningAlert(libtorrent::portmap_error_alert *p);
|
||||||
void handlePortmapAlert(libtorrent::portmap_alert *p);
|
void handlePortmapAlert(libtorrent::portmap_alert *p);
|
||||||
void handlePeerBlockedAlert(libtorrent::peer_blocked_alert *p);
|
void handlePeerBlockedAlert(libtorrent::peer_blocked_alert *p);
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
#include <QDirIterator>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
@ -112,57 +113,51 @@ QString Utils::Fs::folderName(const QString& file_path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove an empty folder tree.
|
* This function will first remove system cache files, e.g. `Thumbs.db`,
|
||||||
*
|
* `.DS_Store`. Then will try to remove the whole tree if the tree consist
|
||||||
* This function will also remove .DS_Store files on Mac OS and
|
* only of folders
|
||||||
* Thumbs.db on Windows.
|
|
||||||
*/
|
*/
|
||||||
bool Utils::Fs::smartRemoveEmptyFolderTree(const QString& dir_path)
|
bool Utils::Fs::smartRemoveEmptyFolderTree(const QString& path)
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO << dir_path;
|
if (!QDir(path).exists())
|
||||||
if (dir_path.isEmpty())
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
QDir dir(dir_path);
|
static const QStringList deleteFilesList = {
|
||||||
if (!dir.exists())
|
// Windows
|
||||||
return true;
|
"Thumbs.db",
|
||||||
|
"desktop.ini",
|
||||||
|
// Linux
|
||||||
|
".directory",
|
||||||
|
// Mac OS
|
||||||
|
".DS_Store"
|
||||||
|
};
|
||||||
|
|
||||||
// Remove Files created by the OS
|
// travel from the deepest folder and remove anything unwanted on the way out.
|
||||||
#if defined Q_OS_MAC
|
QStringList dirList(path + "/"); // get all sub directories paths
|
||||||
forceRemove(dir_path + QLatin1String("/.DS_Store"));
|
QDirIterator iter(path, (QDir::AllDirs | QDir::NoDotAndDotDot), QDirIterator::Subdirectories);
|
||||||
#elif defined Q_OS_WIN
|
while (iter.hasNext())
|
||||||
forceRemove(dir_path + QLatin1String("/Thumbs.db"));
|
dirList << iter.next() + "/";
|
||||||
#endif
|
std::sort(dirList.begin(), dirList.end(), [](const QString &l, const QString &r) { return l.count("/") > r.count("/"); }); // sort descending by directory depth
|
||||||
|
|
||||||
QFileInfoList sub_files = dir.entryInfoList();
|
for (const QString &p : dirList) {
|
||||||
foreach (const QFileInfo& info, sub_files) {
|
// remove unwanted files
|
||||||
QString sub_name = info.fileName();
|
for (const QString &f : deleteFilesList) {
|
||||||
if (sub_name == "." || sub_name == "..")
|
forceRemove(p + f);
|
||||||
continue;
|
|
||||||
|
|
||||||
QString sub_path = info.absoluteFilePath();
|
|
||||||
qDebug() << Q_FUNC_INFO << "sub file: " << sub_path;
|
|
||||||
if (info.isDir()) {
|
|
||||||
if (!smartRemoveEmptyFolderTree(sub_path)) {
|
|
||||||
qWarning() << Q_FUNC_INFO << "Failed to remove folder: " << sub_path;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
if (info.isHidden()) {
|
// remove temp files on linux (file ends with '~'), e.g. `filename~`
|
||||||
qDebug() << Q_FUNC_INFO << "Removing hidden file: " << sub_path;
|
QDir dir(p);
|
||||||
if (!forceRemove(sub_path)) {
|
QStringList tmpFileList = dir.entryList(QDir::Files);
|
||||||
qWarning() << Q_FUNC_INFO << "Failed to remove " << sub_path;
|
for (const QString &f : tmpFileList) {
|
||||||
return false;
|
if (f.endsWith("~"))
|
||||||
}
|
forceRemove(p + f);
|
||||||
}
|
|
||||||
else {
|
|
||||||
qWarning() << Q_FUNC_INFO << "Folder is not empty, aborting. Found: " << sub_path;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove directory if empty
|
||||||
|
dir.rmdir(p);
|
||||||
}
|
}
|
||||||
qDebug() << Q_FUNC_INFO << "Calling rmdir on " << dir_path;
|
|
||||||
return QDir().rmdir(dir_path);
|
return QDir(path).exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -55,7 +55,8 @@ namespace Utils
|
|||||||
bool sameFileNames(const QString& first, const QString& second);
|
bool sameFileNames(const QString& first, const QString& second);
|
||||||
QString expandPath(const QString& path);
|
QString expandPath(const QString& path);
|
||||||
QString expandPathAbs(const QString& path);
|
QString expandPathAbs(const QString& path);
|
||||||
bool smartRemoveEmptyFolderTree(const QString& dir_path);
|
|
||||||
|
bool smartRemoveEmptyFolderTree(const QString& path);
|
||||||
bool forceRemove(const QString& file_path);
|
bool forceRemove(const QString& file_path);
|
||||||
void removeDirRecursive(const QString& dirName);
|
void removeDirRecursive(const QString& dirName);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user