summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorArttu Tarkiainen <arttu.tarkiainen@qt.io>2021-03-02 12:21:18 +0200
committerArttu Tarkiainen <arttu.tarkiainen@qt.io>2021-09-14 14:25:18 +0300
commit50292e14683727e6da81799cedd4ee352c3e0497 (patch)
treeaa4bce967dee16e69aafef653f3c3f9ba1849d6c /tools
parent2076b1384754301ba409b6fe65551eaf55cce401 (diff)
Add support for handling archive files with libarchive
libarchive is a multi-format archive and compression library written in C and licensed under the new BSD license. Usage of libarchive brings in support for additional archive formats (in addition to 7z) with the installer framework, like zip and tar, with several available compression methods like gzip, bzip2 and xz. libarchive will coexist as a supported archive format handler with the LZMA SDK currently used in the framework, which will continue to be used for handling the 7-Zip file format. This change introduces classes for handling archive operations using both libraries, removes most calls to the old Lib7z facade and migrates the code base to use the new handling methods. Task-number: QTIFW-2255 Change-Id: I8d77110ded503060495a3d6fdfdbc26281df9453 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Katja Marttila <katja.marttila@qt.io>
Diffstat (limited to 'tools')
-rw-r--r--tools/archivegen/archive.cpp130
-rw-r--r--tools/devtool/binaryreplace.cpp39
-rw-r--r--tools/repogen/repogen.cpp21
3 files changed, 62 insertions, 128 deletions
diff --git a/tools/archivegen/archive.cpp b/tools/archivegen/archive.cpp
index e1a40a880..56aae1b21 100644
--- a/tools/archivegen/archive.cpp
+++ b/tools/archivegen/archive.cpp
@@ -27,102 +27,19 @@
**************************************************************************/
#include <errors.h>
-#include <lib7z_create.h>
+#include <archivefactory.h>
#include <lib7z_facade.h>
#include <utils.h>
#include <QCoreApplication>
#include <QCommandLineParser>
#include <QDir>
+#include <QMetaEnum>
#include <iostream>
using namespace QInstaller;
-class FailOnErrorCallback : public Lib7z::UpdateCallback
-{
- HRESULT OpenFileError(const wchar_t*, DWORD) Q_DECL_OVERRIDE {
- return S_FALSE;
- }
-
- HRESULT CanNotFindError(const wchar_t*, DWORD) Q_DECL_OVERRIDE {
- return S_FALSE;
- }
-
- HRESULT OpenResult(const wchar_t*, HRESULT result, const wchar_t*) Q_DECL_OVERRIDE {
- return result;
- }
-};
-
-class VerbosePrinterCallback : public Lib7z::UpdateCallback
-{
-public:
- ~VerbosePrinterCallback() {
- m_PercentPrinter.ClosePrint();
- }
-
-private:
- HRESULT SetTotal(UInt64 size) Q_DECL_OVERRIDE {
- m_PercentPrinter.SetTotal(size);
- return S_OK;
- }
-
- HRESULT SetCompleted(const UInt64 *size) Q_DECL_OVERRIDE {
- if (size) {
- m_PercentPrinter.SetRatio(*size);
- m_PercentPrinter.PrintRatio();
- }
- return S_OK;
- }
-
- HRESULT OpenResult(const wchar_t *file, HRESULT result, const wchar_t*) Q_DECL_OVERRIDE {
- if (result != S_OK) {
- printBlock(QCoreApplication::translate("archivegen", "Cannot update file \"%1\". "
- "Unsupported archive.").arg(QDir::toNativeSeparators(QString::fromWCharArray(file))), Q_NULLPTR);
- }
- return result;
- }
-
- HRESULT OpenFileError(const wchar_t *file, DWORD) Q_DECL_OVERRIDE {
- printBlock(QCoreApplication::translate("archivegen", "Cannot open file "), file);
- return S_FALSE;
- }
-
- HRESULT CanNotFindError(const wchar_t *file, DWORD) Q_DECL_OVERRIDE {
- printBlock(QCoreApplication::translate("archivegen", "Cannot find file "), file);
- return S_FALSE;
- }
-
- HRESULT StartArchive(const wchar_t *name, bool) Q_DECL_OVERRIDE {
- printLine(QCoreApplication::translate("archivegen", "Create archive."));
- if (name) {
- m_PercentPrinter.PrintNewLine();
- m_PercentPrinter.PrintString(name);
- }
- return S_OK;
- }
-
- HRESULT FinishArchive() Q_DECL_OVERRIDE {
- m_PercentPrinter.PrintNewLine();
- printLine(QCoreApplication::translate("archivegen", "Finished archive."));
- return S_OK;
- }
-
- void printLine(const QString &message) {
- m_PercentPrinter.PrintString(message.toStdWString().c_str());
- }
-
- void printBlock(const QString &message, const wchar_t *message2) {
- m_PercentPrinter.PrintNewLine();
- m_PercentPrinter.PrintString(message.toStdWString().c_str());
- if (message2)
- m_PercentPrinter.PrintString(message2);
- m_PercentPrinter.PrintNewLine();
- }
-
- Lib7z::PercentPrinter m_PercentPrinter;
-};
-
int main(int argc, char *argv[])
{
try {
@@ -132,12 +49,16 @@ int main(int argc, char *argv[])
QCoreApplication::setApplicationVersion(QLatin1String(QUOTE(IFW_VERSION_STR)));
#undef QUOTE
#undef QUOTE_
-
+ const QString archiveFormats = ArchiveFactory::supportedTypes().join(QLatin1Char('|'));
QCommandLineParser parser;
const QCommandLineOption help = parser.addHelpOption();
const QCommandLineOption version = parser.addVersionOption();
- QCommandLineOption verbose(QLatin1String("verbose"),
- QCoreApplication::translate("archivegen", "Verbose mode. Prints out more information."));
+ const QCommandLineOption format = QCommandLineOption(QStringList()
+ << QLatin1String("f") << QLatin1String("format"),
+ QCoreApplication::translate("archivegen",
+ "%1\n"
+ "Format for the archive. Defaults to 7z."
+ ).arg(archiveFormats), QLatin1String("format"), QLatin1String("7z"));
const QCommandLineOption compression = QCommandLineOption(QStringList()
<< QLatin1String("c") << QLatin1String("compression"),
QCoreApplication::translate("archivegen",
@@ -147,10 +68,12 @@ int main(int argc, char *argv[])
"5 (Normal compressing)\n"
"7 (Maximum compressing)\n"
"9 (Ultra compressing)\n"
- "Defaults to 5 (Normal compression)."
+ "Defaults to 5 (Normal compression).\n"
+ "Note: some formats do not support all the possible values, "
+ "for example bzip2 compression only supports values from 1 to 9."
), QLatin1String("5"), QLatin1String("5"));
- parser.addOption(verbose);
+ parser.addOption(format);
parser.addOption(compression);
parser.addPositionalArgument(QLatin1String("archive"),
QCoreApplication::translate("archivegen", "Compressed archive to create."));
@@ -176,22 +99,29 @@ int main(int argc, char *argv[])
}
bool ok = false;
- const int values[6] = { 0, 1, 3, 5, 7, 9 };
+ QMetaEnum levels = QMetaEnum::fromType<AbstractArchive::CompressionLevel>();
const int value = parser.value(compression).toInt(&ok);
- if (!ok || (std::find(std::begin(values), std::end(values), value) == std::end(values))) {
+ if (!ok || !levels.valueToKey(value)) {
throw QInstaller::Error(QCoreApplication::translate("archivegen",
"Unknown compression level \"%1\". See 'archivgen --help'.").arg(value));
}
Lib7z::initSevenZ();
- Lib7z::createArchive(args[0], args.mid(1), Lib7z::TmpFile::No, Lib7z::Compression(value),
- [&] () -> Lib7z::UpdateCallback * {
- if (parser.isSet(verbose))
- return new VerbosePrinterCallback;
- return new FailOnErrorCallback;
- } ()
- );
- return EXIT_SUCCESS;
+ QString archiveFilename = args[0];
+ // Check if filename already has a supported suffix
+ if (!ArchiveFactory::isSupportedType(archiveFilename))
+ archiveFilename += QLatin1Char('.') + parser.value(format);
+
+ QScopedPointer<AbstractArchive> archive(ArchiveFactory::instance().create(archiveFilename));
+ if (!archive) {
+ throw QInstaller::Error(QString::fromLatin1("Could not create handler "
+ "object for archive \"%1\": \"%2\".").arg(archiveFilename, QLatin1String(Q_FUNC_INFO)));
+ }
+ archive->setCompressionLevel(AbstractArchive::CompressionLevel(value));
+ if (archive->open(QIODevice::WriteOnly) && archive->create(args.mid(1)))
+ return EXIT_SUCCESS;
+
+ std::cerr << archive->errorString() << std::endl;
} catch (const QInstaller::Error &e) {
std::cerr << e.message() << std::endl;
} catch (...) {
diff --git a/tools/devtool/binaryreplace.cpp b/tools/devtool/binaryreplace.cpp
index 97dac37d2..a959bd7dc 100644
--- a/tools/devtool/binaryreplace.cpp
+++ b/tools/devtool/binaryreplace.cpp
@@ -34,9 +34,7 @@
#include <errors.h>
#include <fileio.h>
#include <fileutils.h>
-#include <lib7z_extract.h>
-#include <lib7z_facade.h>
-#include <lib7z_list.h>
+#include <archivefactory.h>
#include <QDir>
#include <QFutureWatcher>
@@ -68,29 +66,22 @@ int BinaryReplace::replace(const QString &source, const QString &target)
return result;
QString newInstallerBasePath = future.result().target();
- if (Lib7z::isSupportedArchive(newInstallerBasePath)) {
- QFile archive(newInstallerBasePath);
- if (archive.open(QIODevice::ReadOnly)) {
- try {
- Lib7z::extractArchive(&archive, QDir::tempPath());
- const QVector<Lib7z::File> files = Lib7z::listArchive(&archive);
- newInstallerBasePath = QDir::tempPath() + QLatin1Char('/') + files.value(0)
- .path;
- result = EXIT_SUCCESS;
- } catch (const Lib7z::SevenZipException& e) {
- std::cerr << qPrintable(QString::fromLatin1("Error while extracting \"%1\": %2")
- .arg(QDir::toNativeSeparators(newInstallerBasePath), e.message())) << std::endl;
- } catch (...) {
- std::cerr << qPrintable(QString::fromLatin1("Unknown exception caught while "
- "extracting \"%1\".").arg(QDir::toNativeSeparators(newInstallerBasePath))) << std::endl;
- }
+ QScopedPointer<QInstaller::AbstractArchive> archive(
+ QInstaller::ArchiveFactory::instance().create(newInstallerBasePath));
+
+ if (archive && archive->open(QIODevice::ReadOnly) && archive->isSupported()) {
+ if (archive->extract(QDir::tempPath())) {
+ const QVector<QInstaller::ArchiveEntry> files = archive->list();
+ newInstallerBasePath = QDir::tempPath() + QLatin1Char('/') + files.value(0).path;
+ result = EXIT_SUCCESS;
} else {
- std::cerr << qPrintable(QString::fromLatin1("Cannot open \"%1\" for reading: %2")
- .arg(QDir::toNativeSeparators(newInstallerBasePath), archive.errorString())) << std::endl;
+ std::cerr << qPrintable(QString::fromLatin1("Error while extracting \"%1\": %2")
+ .arg(QDir::toNativeSeparators(newInstallerBasePath), archive->errorString())) << std::endl;
}
- if (!archive.remove()) {
- std::cerr << qPrintable(QString::fromLatin1("Cannot delete file \"%1\": %2")
- .arg(QDir::toNativeSeparators(newInstallerBasePath), archive.errorString())) << std::endl;
+
+ if (!QFile::remove(newInstallerBasePath)) {
+ std::cerr << qPrintable(QString::fromLatin1("Cannot delete file \"%1\"")
+ .arg(QDir::toNativeSeparators(newInstallerBasePath))) << std::endl;
}
if (result != EXIT_SUCCESS)
return result;
diff --git a/tools/repogen/repogen.cpp b/tools/repogen/repogen.cpp
index b630f8cd3..a709899c6 100644
--- a/tools/repogen/repogen.cpp
+++ b/tools/repogen/repogen.cpp
@@ -34,7 +34,7 @@
#include <settings.h>
#include <utils.h>
#include <loggingutils.h>
-#include <lib7z_facade.h>
+#include <archivefactory.h>
#include <QDomDocument>
#include <QtCore/QDir>
@@ -50,6 +50,8 @@ using namespace QInstaller;
static void printUsage()
{
const QString appName = QFileInfo(QCoreApplication::applicationFilePath()).fileName();
+ const QString archiveFormats = ArchiveFactory::supportedTypes().join(QLatin1Char('|'));
+
std::cout << "Usage: " << appName << " [options] repository-dir" << std::endl;
std::cout << std::endl;
std::cout << "Options:" << std::endl;
@@ -71,6 +73,9 @@ static void printUsage()
std::cout << " download phase." << std::endl;
std::cout << " --component-metadata Creates one metadata 7z per component. " << std::endl;
+ std::cout << " --af|--archive-format " << archiveFormats << std::endl;
+ std::cout << " Set the format used when packaging new component data archives. If" << std::endl;
+ std::cout << " you omit this option the 7z format will be used as a default." << std::endl;
std::cout << std::endl;
std::cout << "Example:" << std::endl;
@@ -105,6 +110,7 @@ int main(int argc, char** argv)
bool updateExistingRepositoryWithNewComponents = false;
bool createUnifiedMetadata = true;
bool createComponentMetadata = true;
+ QString archiveSuffix = QLatin1String("7z");
//TODO: use a for loop without removing values from args like it is in binarycreator.cpp
//for (QStringList::const_iterator it = args.begin(); it != args.end(); ++it) {
@@ -197,6 +203,15 @@ int main(int argc, char** argv)
args.removeFirst();
packagesUpdatedWithSha = args.first().split(QLatin1Char(','));
args.removeFirst();
+ } else if (args.first() == QLatin1String("--af") || args.first() == QLatin1String("--archive-format")) {
+ args.removeFirst();
+ if (args.isEmpty()) {
+ return printErrorAndUsageAndExit(QCoreApplication::translate("QInstaller",
+ "Error: Archive format parameter missing argument"));
+ }
+ // TODO: do we need early check for supported formats?
+ archiveSuffix = args.first();
+ args.removeFirst();
} else {
printUsage();
return 1;
@@ -248,11 +263,9 @@ int main(int argc, char** argv)
tmp.setAutoRemove(false);
tmpMetaDir = tmp.path();
QInstallerTools::createRepository(repoInfo, &packages, tmpMetaDir,
- createComponentMetadata, createUnifiedMetadata);
+ createComponentMetadata, createUnifiedMetadata, archiveSuffix);
exitCode = EXIT_SUCCESS;
- } catch (const Lib7z::SevenZipException &e) {
- std::cerr << "Caught 7zip exception: " << e.message() << std::endl;
} catch (const QInstaller::Error &e) {
std::cerr << "Caught exception: " << e.message() << std::endl;
} catch (...) {