summaryrefslogtreecommitdiffstats
path: root/src/libs
diff options
context:
space:
mode:
authorArttu Tarkiainen <arttu.tarkiainen@qt.io>2022-04-13 17:28:11 +0300
committerArttu Tarkiainen <arttu.tarkiainen@qt.io>2022-04-21 14:24:31 +0000
commite3eef62c1bb7731c8cea64579c39739bd7b27b70 (patch)
tree7738b8c79b79d011feffc940bb4e956451c0035a /src/libs
parent99db65c70ab7cdc458e197440af8251cd48c8e89 (diff)
Fix rollback of extract when archive lists file entries first
At least with the 7z format packaged with a recent archivegen version, the directory entries from archives get processed last when extracting. We remember the path of each extracted entry in the order the writing happens, to be able to undo the extract later. The directories need to be empty for the removing to succeed, so we cannot rely that the entry order from extraction is correct. Ensure files are removed before directories and that the directories are removed in an order starting from the deepest subdirectory level. Task-number: QTIFW-2594 Change-Id: I8a914c4bf69147b845b12f0481c49c93408b51fd Reviewed-by: Katja Marttila <katja.marttila@qt.io>
Diffstat (limited to 'src/libs')
-rw-r--r--src/libs/installer/extractarchiveoperation_p.h24
1 files changed, 22 insertions, 2 deletions
diff --git a/src/libs/installer/extractarchiveoperation_p.h b/src/libs/installer/extractarchiveoperation_p.h
index f440af23b..04b152259 100644
--- a/src/libs/installer/extractarchiveoperation_p.h
+++ b/src/libs/installer/extractarchiveoperation_p.h
@@ -63,6 +63,8 @@ public:
{
Q_ASSERT(m_op != 0);
+ QStringList directories;
+
int removedCounter = 0;
foreach (const QString &file, m_files) {
removedCounter++;
@@ -73,10 +75,28 @@ public:
if (fi.isFile() || fi.isSymLink()) {
m_op->deleteFileNowOrLater(fi.absoluteFilePath());
} else if (fi.isDir()) {
- removeSystemGeneratedFiles(file);
- fi.dir().rmdir(file); // directory may not exist
+ directories.append(file);
}
}
+
+ std::sort(directories.begin(), directories.end(), [](const QString &lhs, const QString &rhs) {
+ // Doesn't match the original creation order, nor will the sorted list be a logical
+ // directory tree. Only requirement is that subdirectories get removed first.
+ const int lhsParts = QDir::fromNativeSeparators(lhs)
+ .split(QLatin1Char('/'), Qt::SkipEmptyParts).size();
+ const int rhsParts = QDir::fromNativeSeparators(rhs)
+ .split(QLatin1Char('/'), Qt::SkipEmptyParts).size();
+
+ if (lhsParts == rhsParts)
+ return lhs < rhs;
+
+ return lhsParts > rhsParts;
+ });
+
+ for (auto &directory : qAsConst(directories)) {
+ removeSystemGeneratedFiles(directory);
+ QDir(directory).rmdir(directory); // directory may not exist
+ }
}
signals: