summaryrefslogtreecommitdiffstats
path: root/src/libs/installer/metadatajob_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/installer/metadatajob_p.h')
-rw-r--r--src/libs/installer/metadatajob_p.h155
1 files changed, 135 insertions, 20 deletions
diff --git a/src/libs/installer/metadatajob_p.h b/src/libs/installer/metadatajob_p.h
index 9160f4cc9..837a7e9ae 100644
--- a/src/libs/installer/metadatajob_p.h
+++ b/src/libs/installer/metadatajob_p.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -29,10 +29,10 @@
#ifndef METADATAJOB_P_H
#define METADATAJOB_P_H
-#include "lib7z_extract.h"
-#include "lib7z_facade.h"
+#include "archivefactory.h"
#include "metadatajob.h"
+#include <QCryptographicHash>
#include <QDir>
#include <QFile>
@@ -47,9 +47,9 @@ public:
: m_message(message)
{}
- void raise() const { throw *this; }
+ void raise() const override { throw *this; }
QString message() const { return m_message; }
- UnzipArchiveException *clone() const { return new UnzipArchiveException(*this); }
+ UnzipArchiveException *clone() const override{ return new UnzipArchiveException(*this); }
private:
QString m_message;
@@ -62,11 +62,18 @@ class UnzipArchiveTask : public AbstractTask<void>
public:
UnzipArchiveTask(const QString &arcive, const QString &target)
- : m_archive(arcive), m_targetDir(target)
+ : m_archive(arcive)
+ , m_targetDir(target)
+ , m_removeArchive(false)
+ , m_storeChecksums(false)
{}
+
QString target() { return m_targetDir; }
QString archive() { return m_archive; }
- void doTask(QFutureInterface<void> &fi)
+ void setRemoveArchive(bool remove) { m_removeArchive = remove; }
+ void setStoreChecksums(bool store) { m_storeChecksums = store; }
+
+ void doTask(QFutureInterface<void> &fi) override
{
fi.reportStarted();
fi.setExpectedResultCount(1);
@@ -76,28 +83,136 @@ public:
return; // ignore already canceled
}
- QFile archive(m_archive);
- if (archive.open(QIODevice::ReadOnly)) {
- try {
- Lib7z::extractArchive(&archive, m_targetDir);
- } catch (const Lib7z::SevenZipException& e) {
- fi.reportException(UnzipArchiveException(MetadataJob::tr("Error while extracting "
- "archive \"%1\": %2").arg(QDir::toNativeSeparators(m_archive), e.message())));
- } catch (...) {
- fi.reportException(UnzipArchiveException(MetadataJob::tr("Unknown exception "
- "caught while extracting archive \"%1\".").arg(QDir::toNativeSeparators(m_archive))));
- }
- } else {
+ QScopedPointer<AbstractArchive> archive(ArchiveFactory::instance().create(m_archive));
+ if (!archive) {
+ fi.reportException(UnzipArchiveException(MetadataJob::tr("Unsupported archive \"%1\": no handler "
+ "registered for file suffix \"%2\".").arg(m_archive, QFileInfo(m_archive).suffix())));
+ return;
+ } else if (!archive->open(QIODevice::ReadOnly)) {
fi.reportException(UnzipArchiveException(MetadataJob::tr("Cannot open file \"%1\" for "
- "reading: %2").arg(QDir::toNativeSeparators(m_archive), archive.errorString())));
+ "reading: %2").arg(QDir::toNativeSeparators(m_archive), archive->errorString())));
+ return;
+ } else if (!archive->extract(m_targetDir)) {
+ fi.reportException(UnzipArchiveException(MetadataJob::tr("Error while extracting "
+ "archive \"%1\": %2").arg(QDir::toNativeSeparators(m_archive), archive->errorString())));
+ return;
+ }
+
+ if (m_storeChecksums) {
+ // Calculate and store checksums of extracted files for later use
+ const QVector<ArchiveEntry> entries = archive->list();
+ for (auto &entry : entries) {
+ if (entry.isDirectory)
+ continue;
+
+ QFile file(m_targetDir + QDir::separator() + entry.path);
+ if (!file.open(QIODevice::ReadOnly)) {
+ fi.reportException(UnzipArchiveException(MetadataJob::tr("Cannot open extracted file \"%1\" for "
+ "reading: %2").arg(QDir::toNativeSeparators(file.fileName()), file.errorString())));
+ break;
+ }
+ QCryptographicHash hash(QCryptographicHash::Sha1);
+ hash.addData(&file);
+
+ const QByteArray hexChecksum = hash.result().toHex();
+ QFileInfo fileInfo(file.fileName());
+ QFile hashFile(fileInfo.absolutePath() + QDir::separator()
+ + QString::fromLatin1(hexChecksum) + QLatin1String(".sha1"));
+ if (!hashFile.open(QIODevice::WriteOnly)) {
+ fi.reportException(UnzipArchiveException(MetadataJob::tr("Cannot open file \"%1\" for "
+ "writing: %2").arg(QDir::toNativeSeparators(hashFile.fileName()), hashFile.errorString())));
+ break;
+ }
+ }
}
+ archive->close();
+ if (m_removeArchive)
+ QFile::remove(m_archive);
+
fi.reportFinished();
}
private:
QString m_archive;
QString m_targetDir;
+ bool m_removeArchive;
+ bool m_storeChecksums;
+};
+
+class CacheTaskException : public QException
+{
+public:
+ CacheTaskException() {}
+ explicit CacheTaskException(const QString &message)
+ : m_message(message)
+ {}
+ ~CacheTaskException() {}
+
+ void raise() const override { throw *this; }
+ QString message() const { return m_message; }
+ CacheTaskException *clone() const override { return new CacheTaskException(*this); }
+
+private:
+ QString m_message;
+};
+
+class UpdateCacheTask : public AbstractTask<void>
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(UpdateCacheTask)
+
+public:
+ UpdateCacheTask(MetadataCache &cache, QHash<QString, Metadata *> &updates)
+ : m_cache(&cache)
+ , m_updates(&updates)
+ {}
+
+ void doTask(QFutureInterface<void> &fi) override
+ {
+ fi.reportStarted();
+ fi.setExpectedResultCount(1);
+
+ // Register items from current run to cache
+ QStringList registeredKeys;
+ bool success = true;
+ for (auto *meta : qAsConst(*m_updates)) {
+ if (!m_cache->registerItem(meta, true, MetadataCache::Move)) {
+ success = false;
+ break;
+ }
+ meta->setPersistentRepositoryPath(meta->repository().url());
+ registeredKeys.append(m_updates->key(meta));
+ }
+ // Remove items whose ownership was transferred to cache
+ for (auto &key : qAsConst(registeredKeys))
+ m_updates->remove(key);
+
+ // Bail out if there was error while registering items
+ if (!success) {
+ fi.reportException(CacheTaskException(m_cache->errorString() + u' '
+ + MetadataJob::tr("Clearing the cache directory and restarting the application may solve this.")));
+ m_cache->sync();
+ fi.reportFinished();
+ return;
+ }
+
+ // ...and clean up obsolete cached items
+ const QList<Metadata *> obsolete = m_cache->obsoleteItems();
+ for (auto *meta : obsolete)
+ m_cache->removeItem(meta->checksum());
+
+ if (!m_cache->sync()) {
+ fi.reportException(CacheTaskException(m_cache->errorString() + u' '
+ + MetadataJob::tr("Clearing the cache directory and restarting the application may solve this.")));
+ }
+
+ fi.reportFinished();
+ }
+
+private:
+ MetadataCache *const m_cache;
+ QHash<QString, Metadata *> *const m_updates;
};
} // namespace QInstaller