diff options
Diffstat (limited to 'tools/devtool')
-rw-r--r-- | tools/devtool/binarydump.cpp | 20 | ||||
-rw-r--r-- | tools/devtool/binaryreplace.cpp | 24 | ||||
-rw-r--r-- | tools/devtool/main.cpp | 149 | ||||
-rw-r--r-- | tools/devtool/operationrunner.cpp | 6 |
4 files changed, 141 insertions, 58 deletions
diff --git a/tools/devtool/binarydump.cpp b/tools/devtool/binarydump.cpp index 4a6094e66..26e8260dd 100644 --- a/tools/devtool/binarydump.cpp +++ b/tools/devtool/binarydump.cpp @@ -47,19 +47,19 @@ int BinaryDump::dump(const QInstaller::ResourceCollectionManager &manager, const QDir targetDir(QFileInfo(target).absoluteFilePath()); if (targetDir.exists()) { if (!targetDir.entryList(QDir::NoDotAndDotDot | QDir::AllEntries).isEmpty()) { - std::cerr << qPrintable(QString::fromLatin1("Target directory '%1' already exists and " - "is not empty.").arg(targetDir.path())) << std::endl; + std::cerr << qPrintable(QString::fromLatin1("Target directory \"%1\" already exists and " + "is not empty.").arg(QDir::toNativeSeparators(targetDir.path()))) << std::endl; return EXIT_FAILURE; } } else { if (!QDir().mkpath(targetDir.path())) { - std::cerr << qPrintable(QString::fromLatin1("Could not create '%1'.").arg(targetDir - .path())) << std::endl; + std::cerr << qPrintable(QString::fromLatin1("Cannot create \"%1\".").arg( + QDir::toNativeSeparators(targetDir.path()))) << std::endl; return EXIT_FAILURE; } } - QInstaller::CopyDirectoryOperation copyMetadata; + QInstaller::CopyDirectoryOperation copyMetadata(0); copyMetadata.setArguments(QStringList() << QLatin1String(":/") << (targetDir.path() + QLatin1Char('/'))); // Add "/" at the end to make operation work. if (!copyMetadata.performOperation()) { @@ -68,8 +68,8 @@ int BinaryDump::dump(const QInstaller::ResourceCollectionManager &manager, const } if (!targetDir.cd(QLatin1String("metadata"))) { - std::cerr << qPrintable(QString::fromLatin1("Could not switch to '%1/metadata'.") - .arg(targetDir.path())) << std::endl; + std::cerr << qPrintable(QString::fromLatin1("Cannot switch to \"%1/metadata\".") + .arg(QDir::toNativeSeparators(targetDir.path()))) << std::endl; return EXIT_FAILURE; } @@ -81,8 +81,8 @@ int BinaryDump::dump(const QInstaller::ResourceCollectionManager &manager, const QString error; QDomDocument doc; if (!doc.setContent(&updatesXml, &error)) { - throw QInstaller::Error(QString::fromLatin1("Could not read: '%1'. %2").arg(updatesXml - .fileName(), error)); + throw QInstaller::Error(QString::fromLatin1("Cannot read: \"%1\": %2").arg( + QDir::toNativeSeparators(updatesXml.fileName()), error)); } QHash<QString, QString> versionMap; @@ -113,7 +113,7 @@ int BinaryDump::dump(const QInstaller::ResourceCollectionManager &manager, const continue; if (!targetDir.mkpath(name)) { - throw QInstaller::Error(QString::fromLatin1("Could not create target dir: %1.") + throw QInstaller::Error(QString::fromLatin1("Cannot create target dir: %1.") .arg(targetDir.filePath(name))); } diff --git a/tools/devtool/binaryreplace.cpp b/tools/devtool/binaryreplace.cpp index 65f124a7a..910526b6a 100644 --- a/tools/devtool/binaryreplace.cpp +++ b/tools/devtool/binaryreplace.cpp @@ -39,7 +39,9 @@ #include <errors.h> #include <fileio.h> #include <fileutils.h> +#include <lib7z_extract.h> #include <lib7z_facade.h> +#include <lib7z_list.h> #include <QDir> #include <QFutureWatcher> @@ -81,19 +83,19 @@ int BinaryReplace::replace(const QString &source, const QString &target) .path; result = EXIT_SUCCESS; } catch (const Lib7z::SevenZipException& e) { - std::cerr << qPrintable(QString::fromLatin1("Error while extracting '%1': %2.") - .arg(newInstallerBasePath, e.message())) << std::endl; + 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(newInstallerBasePath)) << std::endl; + "extracting \"%1\".").arg(QDir::toNativeSeparators(newInstallerBasePath))) << std::endl; } } else { - std::cerr << qPrintable(QString::fromLatin1("Could not open '%1' for reading: %2.") - .arg(newInstallerBasePath, archive.errorString())) << std::endl; + std::cerr << qPrintable(QString::fromLatin1("Cannot open \"%1\" for reading: %2") + .arg(QDir::toNativeSeparators(newInstallerBasePath), archive.errorString())) << std::endl; } if (!archive.remove()) { - std::cerr << qPrintable(QString::fromLatin1("Could not delete file '%1': %2.") - .arg(newInstallerBasePath, archive.errorString())) << std::endl; + std::cerr << qPrintable(QString::fromLatin1("Cannot delete file \"%1\": %2") + .arg(QDir::toNativeSeparators(newInstallerBasePath), archive.errorString())) << std::endl; } if (result != EXIT_SUCCESS) return result; @@ -130,19 +132,19 @@ int BinaryReplace::replace(const QString &source, const QString &target) #endif QFile backup(installerBaseOld.fileName() + QLatin1String(".bak")); if (backup.exists() && (!backup.remove())) { - std::cerr << qPrintable(QString::fromLatin1("Could not delete '%1'. %2") - .arg(backup.fileName(), backup.errorString())) << std::endl; + std::cerr << qPrintable(QString::fromLatin1("Cannot delete \"%1\": %2") + .arg(QDir::toNativeSeparators(backup.fileName()), backup.errorString())) << std::endl; } const QString oldBasePath = installerBaseOld.fileName(); if (!installerBaseOld.rename(oldBasePath + QLatin1String(".bak"))) { - std::cerr << qPrintable(QString::fromLatin1("Could not rename '%1' to '%2'. %3") + std::cerr << qPrintable(QString::fromLatin1("Cannot rename \"%1\" to \"%2\": %3") .arg(oldBasePath, oldBasePath + QLatin1String(".bak"), installerBaseOld.errorString())) << std::endl; } if (!installerBaseNew.rename(oldBasePath)) { - std::cerr << qPrintable(QString::fromLatin1("Could not copy '%1' to '%2'. %3") + std::cerr << qPrintable(QString::fromLatin1("Cannot copy \"%1\" to \"%2\": %3") .arg(installerBaseNew.fileName(), oldBasePath, installerBaseNew.errorString())) << std::endl; } else { diff --git a/tools/devtool/main.cpp b/tools/devtool/main.cpp index df9b8bbc7..c9aaab71c 100644 --- a/tools/devtool/main.cpp +++ b/tools/devtool/main.cpp @@ -36,7 +36,6 @@ #include "operationrunner.h" #include <binarycontent.h> -#include <binaryformat.h> #include <binaryformatenginehandler.h> #include <errors.h> #include <fileio.h> @@ -49,39 +48,122 @@ #include <QFileInfo> #include <QResource> +#include <iomanip> #include <iostream> +struct Command +{ + const char* command; + const char* description; + qint32 argC; + const char* arguments; + const char* argDescription; +} Commands[] = { + { "dump", "Dumps the binary content that belongs to an installer or maintenance tool into " + "target directory.", 2, "<binary> <targetdirecory>", "The <binary> containing the data to " + "dump.\nThe <targetdirectory> to dump the data in." + }, + + { "update", "Updates existing installer or maintenance tool with a new installer base.", 2, + "<binary> <installerbase>", "The <binary> to update.\nThe <installerbase> to use as update." + }, + + { "operation", "Executes an operation with with a given mode and a list of arguments. ", 2, + "<binary> <mode,name,args,...>", "The <binary> to run the operation with.\n" + "<mode,name,args,...> 'mode' can be DO or UNDO. 'name' of the operation. 'args,...' " + "used to run the operation." + } +}; + +#define DESCRITION_LENGTH 60 +#define SETW_ALIGNLEFT(X) std::setw(X) << std::setiosflags(std::ios::left) + +static int fail(const QString &message) +{ + std::cerr << qPrintable(message) << " See 'devtool --help'." << std::endl; + return EXIT_FAILURE; +} + +static QStringList split(int index, const QString &description) +{ + QStringList result; + if (description.length() <= DESCRITION_LENGTH) + return result << description; + + const int lastIndexOf = description.left(index + DESCRITION_LENGTH) + .lastIndexOf(QLatin1Char(' ')); + result << description.left(lastIndexOf); + return result + split(lastIndexOf + 1, description.mid(lastIndexOf + 1)); +} + +// -- main + int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); app.setApplicationVersion(QLatin1String("1.0.0")); - QCommandLineOption verbose(QLatin1String("verbose"), - QLatin1String("Verbose mode. Prints out more information.")); - QCommandLineOption dump(QLatin1String("dump"), - QLatin1String("Dumps the binary content that belongs to an installer or maintenance tool " - "into target."), QLatin1String("folder")); - QCommandLineOption run(QLatin1String("operation"), - QLatin1String("Executes an operation with a list of arguments. Mode can be DO or UNDO."), - QLatin1String("mode,name,args,...")); - QCommandLineOption update(QLatin1String("update"), - QLatin1String("Updates existing installer or maintenance tool with a new installer base."), - QLatin1String("file")); - QCommandLineParser parser; - parser.addHelpOption(); - parser.addVersionOption(); + QCommandLineOption help = parser.addHelpOption(); + QCommandLineOption version = parser.addVersionOption(); + QCommandLineOption verbose(QLatin1String("verbose"), QLatin1String("Verbose mode. Prints out " + "more information.")); parser.addOption(verbose); - parser.addOption(update); - parser.addOption(dump); - parser.addOption(run); - parser.addPositionalArgument(QLatin1String("binary"), QLatin1String("Existing installer or " - "maintenance tool.")); - parser.process(app.arguments()); - const QStringList arguments = parser.positionalArguments(); - if (arguments.isEmpty() || (arguments.count() > 1)) - parser.showHelp(EXIT_FAILURE); + parser.parse(app.arguments()); + if (parser.isSet(version)) { + parser.showVersion(); + return EXIT_SUCCESS; + } + + if (parser.isSet(help)) { + const QString command = parser.positionalArguments().value(0); + if (!command.isEmpty()) { + for (const auto &c : Commands) { + if (QLatin1String(c.command) == command) { + parser.clearPositionalArguments(); + parser.addPositionalArgument(QString::fromLatin1("%1 %2").arg(QLatin1String(c + .command), QLatin1String(c.arguments)), QLatin1String(c.argDescription)); + parser.showHelp(EXIT_SUCCESS); + } + } + return fail(QString::fromLatin1("\"%1\" is not a devtool command.").arg(command)); + } + + QString helpText = parser.helpText(); + helpText.insert(helpText.indexOf(QLatin1Char(']')) + 1, QLatin1String(" command <args>")); + std::cout << qPrintable(helpText) << std::endl; + std::cout << "Available commands (mutually exclusive):" << std::endl; + for (const auto &c : Commands) { + QStringList lines = split(0, QLatin1String(c.description)); + std::cout << SETW_ALIGNLEFT(2) << " " << SETW_ALIGNLEFT(16) << c.command + << SETW_ALIGNLEFT(DESCRITION_LENGTH) << qPrintable(lines.takeFirst()) << std::endl; + foreach (const QString &line, lines) { + std::cout << SETW_ALIGNLEFT(18) << QByteArray(18, ' ').constData() + << qPrintable(line) << std::endl; + } + } + std::cout << std::endl << "Use 'devtool --help <command>' to read about a specific command." + << std::endl; + return EXIT_SUCCESS; + } + + QStringList arguments = parser.positionalArguments(); + if (arguments.isEmpty()) + return fail(QLatin1String("Missing command.")); + + bool found = false; + const QString command = arguments.takeFirst(); + for (const auto &c : Commands) { + if ((found = (QLatin1String(c.command) == command))) { + if (arguments.count() != c.argC) + return fail(QString::fromLatin1("%1: wrong argument count.").arg(command)); + break; + } + } + + if (!found) + return fail(QString::fromLatin1("\"%1\" is not a devtool command.").arg(command)); QInstaller::init(); QInstaller::setVerbose(parser.isSet(verbose)); @@ -100,7 +182,7 @@ int main(int argc, char *argv[]) QInstaller::openForRead(&tmp); if (!tmp.seek(QInstaller::BinaryContent::findMagicCookie(&tmp, cookie) - sizeof(qint64))) - throw QInstaller::Error(QLatin1String("Could not seek to read magic marker.")); + throw QInstaller::Error(QLatin1String("Cannot seek to read magic marker.")); QInstaller::BinaryLayout layout; layout.magicMarker = QInstaller::retrieveInt64(&tmp); @@ -120,9 +202,9 @@ int main(int argc, char *argv[]) layout = QInstaller::BinaryContent::binaryLayout(&tmp, cookie); tmp.close(); - if (parser.isSet(update)) { + if (command == QLatin1String("update")) { BinaryReplace br(layout); // To update the binary we do not need any mapping. - return br.replace(parser.value(update), QFileInfo(arguments.first()) + return br.replace(arguments.last(), QFileInfo(arguments.first()) .absoluteFilePath()); } } @@ -145,28 +227,29 @@ int main(int argc, char *argv[]) const QByteArray ba = resource->readAll(); if (!QResource::registerResource((const uchar*) ba.data(), QLatin1String(":/metadata"))) - throw QInstaller::Error(QLatin1String("Could not register in-binary resource.")); + throw QInstaller::Error(QLatin1String("Cannot register in-binary resource.")); resourceMappings.append(ba); if (!isOpen) resource->close(); } - if (parser.isSet(dump)) { + if (command == QLatin1String("dump")) { // To dump the content we do not need the binary format engine. BinaryDump bd; - result = bd.dump(manager, parser.value(dump)); - } else if (parser.isSet(run)) { + result = bd.dump(manager, arguments.last()); + } else if (command == QLatin1String("operation")) { QInstaller::BinaryFormatEngineHandler::instance()->registerResources(manager .collections()); // setup the binary format engine OperationRunner runner(magicMarker, operations); - const QStringList arguments = parser.value(run).split(QLatin1Char(',')); + const QStringList arguments = arguments.last().split(QLatin1Char(',')); if (arguments.first() == QLatin1String("DO")) result = runner.runOperation(arguments.mid(1), OperationRunner::RunMode::Do); else if (arguments.first() == QLatin1String("UNDO")) result = runner.runOperation(arguments.mid(1), OperationRunner::RunMode::Undo); else - std::cerr << "Malformed argument: " << qPrintable(parser.value(run)) << std::endl; + std::cerr << "Malformed argument: " << qPrintable(arguments.last()) << std::endl; + } } catch (const QInstaller::Error &error) { std::cerr << qPrintable(error.message()) << std::endl; diff --git a/tools/devtool/operationrunner.cpp b/tools/devtool/operationrunner.cpp index 97bdfd7d7..41cc9d41b 100644 --- a/tools/devtool/operationrunner.cpp +++ b/tools/devtool/operationrunner.cpp @@ -34,7 +34,7 @@ #include "operationrunner.h" #include <errors.h> -#include <kdupdaterupdateoperationfactory.h> +#include <updateoperationfactory.h> #include <packagemanagercore.h> #include <QMetaObject> @@ -59,7 +59,7 @@ int OperationRunner::runOperation(QStringList arguments, RunMode mode) try { const QString name = arguments.takeFirst(); QScopedPointer<QInstaller::Operation> op(KDUpdater::UpdateOperationFactory::instance() - .create(name)); + .create(name, m_core)); if (!op) { std::cerr << "Cannot instantiate operation: " << qPrintable(name) << std::endl; return EXIT_FAILURE; @@ -71,8 +71,6 @@ int OperationRunner::runOperation(QStringList arguments, RunMode mode) connect(object, SIGNAL(outputTextChanged(QString)), this, SLOT(print(QString))); } op->setArguments(arguments); - op->setValue(QLatin1String("installer"), QVariant::fromValue(m_core)); - bool readyPerformed = false; if (mode == RunMode::Do) |