Don't unnecessarily delete OS files in folders

This commit is contained in:
sledgehammer999 2019-12-14 01:36:21 +02:00
parent d051519eff
commit 64e5d41a2c
No known key found for this signature in database
GPG Key ID: 6E4A2D025B7CC9A2

View File

@ -99,9 +99,13 @@ QString Utils::Fs::folderName(const QString &filePath)
} }
/** /**
* This function will first remove system cache files, e.g. `Thumbs.db`, * This function will first check if there are only system cache files, e.g. `Thumbs.db`,
* `.DS_Store`. Then will try to remove the whole tree if the tree consist * `.DS_Store` and/or only temp files that end with '~', e.g. `filename~`.
* only of folders * If they are the only files it will try to remove them and delete the folder.
* This action will be performed for each subfolder starting from the deepest folder.
* There is an inherent race condition here. A file might appear after it is checked
* that only the above mentioned "useless" files exist but before the whole folder is removed.
* In this case, the folder will not be removed but the "useless" files will be deleted.
*/ */
bool Utils::Fs::smartRemoveEmptyFolderTree(const QString &path) bool Utils::Fs::smartRemoveEmptyFolderTree(const QString &path)
{ {
@ -110,12 +114,12 @@ bool Utils::Fs::smartRemoveEmptyFolderTree(const QString &path)
const QStringList deleteFilesList = { const QStringList deleteFilesList = {
// Windows // Windows
"Thumbs.db", QLatin1String("Thumbs.db"),
"desktop.ini", QLatin1String("desktop.ini"),
// Linux // Linux
".directory", QLatin1String(".directory"),
// Mac OS // Mac OS
".DS_Store" QLatin1String(".DS_Store")
}; };
// travel from the deepest folder and remove anything unwanted on the way out. // travel from the deepest folder and remove anything unwanted on the way out.
@ -128,18 +132,25 @@ bool Utils::Fs::smartRemoveEmptyFolderTree(const QString &path)
, [](const QString &l, const QString &r) { return l.count('/') > r.count('/'); }); , [](const QString &l, const QString &r) { return l.count('/') > r.count('/'); });
for (const QString &p : asConst(dirList)) { for (const QString &p : asConst(dirList)) {
// remove unwanted files
for (const QString &f : deleteFilesList) {
forceRemove(p + f);
}
// remove temp files on linux (file ends with '~'), e.g. `filename~`
const QDir dir(p); const QDir dir(p);
// A deeper folder may have not been removed in the previous iteration
// so don't remove anything from this folder either.
if (!dir.isEmpty(QDir::Dirs | QDir::NoDotAndDotDot))
continue;
const QStringList tmpFileList = dir.entryList(QDir::Files); const QStringList tmpFileList = dir.entryList(QDir::Files);
for (const QString &f : tmpFileList) {
if (f.endsWith('~')) // deleteFilesList contains unwanted files, usually created by the OS
// temp files on linux usually end with '~', e.g. `filename~`
const bool hasOtherFiles = std::any_of(tmpFileList.cbegin(), tmpFileList.cend(), [&deleteFilesList](const QString &f)
{
return (!f.endsWith('~') && !deleteFilesList.contains(f, Qt::CaseInsensitive));
});
if (hasOtherFiles)
continue;
for (const QString &f : tmpFileList)
forceRemove(p + f); forceRemove(p + f);
}
// remove directory if empty // remove directory if empty
dir.rmdir(p); dir.rmdir(p);