2011-02-21 16:30:31 +01:00
|
|
|
/**************************************************************************
|
|
|
|
**
|
2012-02-06 09:23:20 +01:00
|
|
|
** This file is part of Installer Framework
|
2011-02-21 16:30:31 +01:00
|
|
|
**
|
2012-02-06 09:23:20 +01:00
|
|
|
** Copyright (c) 2011-2012 Nokia Corporation and/or its subsidiary(-ies).
|
2011-02-21 16:30:31 +01:00
|
|
|
**
|
2012-02-06 11:30:37 +01:00
|
|
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
2011-02-21 16:30:31 +01:00
|
|
|
**
|
|
|
|
**
|
|
|
|
** GNU Lesser General Public License Usage
|
|
|
|
**
|
|
|
|
** This file may be used under the terms of the GNU Lesser General Public
|
|
|
|
** License version 2.1 as published by the Free Software Foundation and
|
|
|
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
|
|
|
** Please review the following information to ensure the GNU Lesser General
|
|
|
|
** Public License version 2.1 requirements will be met:
|
|
|
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
|
|
**
|
|
|
|
** In addition, as a special exception, Nokia gives you certain additional
|
2012-02-06 09:23:20 +01:00
|
|
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
**
|
|
|
|
** Other Usage
|
2011-02-21 16:30:31 +01:00
|
|
|
**
|
2012-02-06 09:23:20 +01:00
|
|
|
** Alternatively, this file may be used in accordance with the terms and
|
|
|
|
** conditions contained in a signed written agreement between you and Nokia.
|
|
|
|
**
|
|
|
|
** If you have questions regarding the use of this file, please contact
|
2012-02-06 11:30:37 +01:00
|
|
|
** Nokia at qt-info@nokia.com.
|
2011-02-21 16:30:31 +01:00
|
|
|
**
|
|
|
|
**************************************************************************/
|
2012-03-13 16:38:56 +01:00
|
|
|
#include "repositorygen.h"
|
|
|
|
|
|
|
|
#include <fileutils.h>
|
|
|
|
#include <errors.h>
|
2012-02-28 15:01:08 +01:00
|
|
|
#include <lib7z_facade.h>
|
2011-06-20 22:00:34 +02:00
|
|
|
#include <settings.h>
|
2012-03-27 13:55:25 +02:00
|
|
|
#include <qinstallerglobal.h>
|
2012-09-28 14:46:17 +02:00
|
|
|
#include <utils.h>
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2012-03-13 16:38:56 +01:00
|
|
|
#include <kdupdater.h>
|
|
|
|
|
2012-02-28 15:01:08 +01:00
|
|
|
#include <QtCore/QDirIterator>
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2012-03-27 13:55:25 +02:00
|
|
|
#include <QtScript/QScriptEngine>
|
|
|
|
|
2012-02-28 15:01:08 +01:00
|
|
|
#include <QtXml/QDomDocument>
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2012-03-07 16:47:08 +01:00
|
|
|
#include <iostream>
|
|
|
|
|
2012-03-13 21:07:12 +01:00
|
|
|
using namespace QInstallerTools;
|
2012-03-13 17:53:03 +01:00
|
|
|
|
|
|
|
void QInstallerTools::printRepositoryGenOptions()
|
2012-03-07 16:47:08 +01:00
|
|
|
{
|
2012-04-03 08:43:33 +02:00
|
|
|
std::cout << " -c|--config file The file containing the installer configuration" << std::endl;
|
2012-03-07 16:47:08 +01:00
|
|
|
|
|
|
|
std::cout << " -p|--packages dir The directory containing the available packages." << std::endl;
|
|
|
|
std::cout << " Defaults to the current working directory." << std::endl;
|
|
|
|
|
2012-03-09 12:06:05 +01:00
|
|
|
std::cout << " -e|--exclude p1,...,pn Exclude the given packages." << std::endl;
|
2012-03-20 15:04:14 +01:00
|
|
|
std::cout << " -i|--include p1,...,pn Include the given packages and their dependencies" << std::endl;
|
|
|
|
std::cout << " from the repository." << std::endl;
|
|
|
|
|
2012-03-07 16:47:47 +01:00
|
|
|
std::cout << " --ignore-translations Don't use any translation" << std::endl;
|
|
|
|
std::cout << " --ignore-invalid-packages Ignore all invalid packages instead of aborting." << std::endl;
|
2012-03-07 16:47:08 +01:00
|
|
|
}
|
|
|
|
|
2012-05-14 15:32:58 +02:00
|
|
|
void QInstallerTools::compressPaths(const QStringList &paths, const QString &archivePath)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
|
|
|
QFile archive(archivePath);
|
2012-03-13 17:53:03 +01:00
|
|
|
QInstaller::openForWrite(&archive, archivePath);
|
2011-08-30 16:58:11 +02:00
|
|
|
Lib7z::createArchive(&archive, paths);
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
2012-03-13 17:53:03 +01:00
|
|
|
void QInstallerTools::compressMetaDirectories(const QString &repoDir)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
|
|
|
QDir dir(repoDir);
|
|
|
|
const QStringList sub = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
|
2011-11-17 22:44:56 +01:00
|
|
|
foreach (const QString &i, sub) {
|
2011-02-21 16:30:31 +01:00
|
|
|
QDir sd(dir);
|
|
|
|
sd.cd(i);
|
|
|
|
const QString absPath = sd.absolutePath();
|
|
|
|
const QString fn = QLatin1String("meta.7z");
|
|
|
|
const QString tmpTarget = repoDir + QLatin1String("/") +fn;
|
2012-05-14 15:32:58 +02:00
|
|
|
compressPaths(QStringList() << absPath, tmpTarget);
|
2011-02-21 16:30:31 +01:00
|
|
|
QFile tmp(tmpTarget);
|
|
|
|
const QString finalTarget = absPath + QLatin1String("/") + fn;
|
|
|
|
if (!tmp.rename(finalTarget)) {
|
2012-09-27 17:49:31 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Could not move file from \"%1\" to \"%2\"").arg(tmpTarget,
|
2011-02-21 16:30:31 +01:00
|
|
|
finalTarget));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-13 17:53:03 +01:00
|
|
|
void QInstallerTools::generateMetaDataDirectory(const QString &outDir, const QString &dataDir,
|
2012-02-28 15:05:51 +01:00
|
|
|
const PackageInfoVector &packages, const QString &appName, const QString &appVersion,
|
2011-11-03 13:51:32 +01:00
|
|
|
const QString &redirectUpdateUrl)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2011-11-03 13:51:32 +01:00
|
|
|
QString metapath = outDir;
|
2011-02-21 16:30:31 +01:00
|
|
|
if (QFileInfo(metapath).isRelative())
|
|
|
|
metapath = QDir::cleanPath(QDir::current().absoluteFilePath(metapath));
|
2012-01-16 23:42:54 +01:00
|
|
|
qDebug() << "Generating meta data...";
|
2011-02-21 16:30:31 +01:00
|
|
|
|
|
|
|
if (!QFile::exists(metapath))
|
|
|
|
QInstaller::mkpath(metapath);
|
|
|
|
|
|
|
|
QDomDocument doc;
|
|
|
|
QDomElement root;
|
|
|
|
// use existing Updates.xml, if any
|
|
|
|
QFile existingUpdatesXml(QFileInfo(dataDir, QLatin1String("Updates.xml")).absoluteFilePath());
|
|
|
|
if (!existingUpdatesXml.open(QIODevice::ReadOnly) || !doc.setContent(&existingUpdatesXml)) {
|
2012-03-15 14:53:47 +01:00
|
|
|
root = doc.createElement(QLatin1String("Updates"));
|
|
|
|
root.appendChild(doc.createElement(QLatin1String("ApplicationName"))).appendChild(
|
2011-02-21 16:30:31 +01:00
|
|
|
doc.createTextNode(appName));
|
2012-03-15 14:53:47 +01:00
|
|
|
root.appendChild(doc.createElement(QLatin1String("ApplicationVersion"))).appendChild(
|
2011-02-21 16:30:31 +01:00
|
|
|
doc.createTextNode(appVersion));
|
2012-03-15 14:53:47 +01:00
|
|
|
root.appendChild(doc.createElement(QLatin1String("Checksum"))).appendChild(
|
2011-02-21 16:30:31 +01:00
|
|
|
doc.createTextNode(QLatin1String("true")));
|
2011-11-03 13:51:32 +01:00
|
|
|
if (!redirectUpdateUrl.isEmpty()) {
|
2012-03-15 14:53:47 +01:00
|
|
|
root.appendChild(doc.createElement(QLatin1String("RedirectUpdateUrl"))).appendChild(
|
2011-11-03 13:51:32 +01:00
|
|
|
doc.createTextNode(redirectUpdateUrl));
|
|
|
|
}
|
2011-02-21 16:30:31 +01:00
|
|
|
} else {
|
|
|
|
root = doc.documentElement();
|
|
|
|
}
|
|
|
|
|
2012-02-28 15:05:51 +01:00
|
|
|
for (PackageInfoVector::const_iterator it = packages.begin(); it != packages.end(); ++it) {
|
2011-02-21 16:30:31 +01:00
|
|
|
const QString packageXmlPath = QString::fromLatin1("%1/meta/package.xml").arg(it->directory);
|
2012-02-21 10:58:27 +01:00
|
|
|
qDebug() << QString::fromLatin1("\tGenerating meta data for package %1 using %2.").arg(
|
2012-01-16 23:42:54 +01:00
|
|
|
it->name, packageXmlPath);
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2012-02-21 10:58:27 +01:00
|
|
|
// remove existing entry for this component from existing Updates.xml
|
2011-02-21 16:30:31 +01:00
|
|
|
const QDomNodeList packageNodes = root.childNodes();
|
|
|
|
for (int i = 0; i < packageNodes.count(); ++i) {
|
|
|
|
const QDomNode node = packageNodes.at(i);
|
|
|
|
if (node.nodeName() != QLatin1String("PackageUpdate"))
|
|
|
|
continue;
|
|
|
|
if (node.firstChildElement(QLatin1String("Name")).text() != it->name)
|
|
|
|
continue;
|
|
|
|
root.removeChild(node);
|
|
|
|
--i;
|
|
|
|
}
|
|
|
|
|
|
|
|
QDomDocument packageXml;
|
|
|
|
QFile file(packageXmlPath);
|
2012-03-13 17:53:03 +01:00
|
|
|
QInstaller::openForRead(&file, packageXmlPath);
|
2011-02-21 16:30:31 +01:00
|
|
|
QString errMsg;
|
|
|
|
int col = 0;
|
|
|
|
int line = 0;
|
|
|
|
if (!packageXml.setContent(&file, &errMsg, &line, &col)) {
|
2012-09-27 17:49:31 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Could not parse \"%1\": line: %2, column: %3: %4 (%5)")
|
2012-03-13 17:53:03 +01:00
|
|
|
.arg(packageXmlPath, QString::number(line), QString::number(col), errMsg, it->name));
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
2012-03-15 14:53:47 +01:00
|
|
|
const QDomNode package = packageXml.firstChildElement(QLatin1String("Package"));
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2012-03-15 14:53:47 +01:00
|
|
|
QDomElement update = doc.createElement(QLatin1String("PackageUpdate"));
|
2012-09-27 15:50:36 +02:00
|
|
|
QDomElement nameElement = doc.createElement(QLatin1String("Name"));
|
|
|
|
nameElement.appendChild(doc.createTextNode(it->name));
|
|
|
|
update.appendChild(nameElement);
|
|
|
|
|
|
|
|
// list of current unused or later transformed tags
|
|
|
|
QStringList blackList;
|
|
|
|
blackList << QLatin1String("UserInterfaces") << QLatin1String("Translations") <<
|
|
|
|
QLatin1String("Licenses") << QLatin1String("Name");
|
2011-02-21 16:30:31 +01:00
|
|
|
|
|
|
|
const QDomNodeList childNodes = package.childNodes();
|
|
|
|
for (int i = 0; i < childNodes.count(); ++i) {
|
|
|
|
const QDomNode node = childNodes.at(i);
|
|
|
|
const QString key = node.nodeName();
|
2012-09-27 15:50:36 +02:00
|
|
|
// just skip comments and some tags...
|
|
|
|
if (node.isComment() || blackList.contains(key))
|
2011-02-21 16:30:31 +01:00
|
|
|
continue;
|
|
|
|
const QString value = node.toElement().text();
|
2011-10-13 13:28:59 +02:00
|
|
|
QDomElement element = doc.createElement(key);
|
|
|
|
for (int i = 0; i < node.attributes().size(); i++) {
|
|
|
|
element.setAttribute(node.attributes().item(i).toAttr().name(),
|
2012-02-28 15:01:08 +01:00
|
|
|
node.attributes().item(i).toAttr().value());
|
2011-10-13 13:28:59 +02:00
|
|
|
}
|
|
|
|
update.appendChild(element).appendChild(doc.createTextNode(value));
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// get the size of the data
|
|
|
|
quint64 componentSize = 0;
|
|
|
|
quint64 compressedComponentSize = 0;
|
|
|
|
|
2012-11-07 14:07:05 +01:00
|
|
|
const QDir::Filters filters = QDir::Files | QDir::NoDotAndDotDot;
|
|
|
|
const QDir cmpDataDir = QString::fromLatin1("%1/%2/data").arg(dataDir, it->name);
|
|
|
|
const QFileInfoList entries = cmpDataDir.exists() ? cmpDataDir.entryInfoList(filters | QDir::Dirs)
|
|
|
|
: QDir(QString::fromLatin1("%1/%2").arg(dataDir, it->name)).entryInfoList(filters);
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2011-11-17 22:44:56 +01:00
|
|
|
foreach (const QFileInfo &fi, entries) {
|
2011-02-21 16:30:31 +01:00
|
|
|
if (fi.isHidden())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (fi.isDir()) {
|
|
|
|
QDirIterator recursDirIt(fi.filePath(), QDirIterator::Subdirectories);
|
|
|
|
while (recursDirIt.hasNext()) {
|
2012-11-07 14:07:05 +01:00
|
|
|
const quint64 size = QFile(recursDirIt.next()).size();
|
|
|
|
componentSize += size;
|
|
|
|
compressedComponentSize += size;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
} else if (Lib7z::isSupportedArchive(fi.filePath())) {
|
2012-02-15 13:39:53 +01:00
|
|
|
// if it's an archive already, list its files and sum the uncompressed sizes
|
2011-02-21 16:30:31 +01:00
|
|
|
QFile archive(fi.filePath());
|
|
|
|
compressedComponentSize += archive.size();
|
|
|
|
archive.open(QIODevice::ReadOnly);
|
|
|
|
const QVector< Lib7z::File > files = Lib7z::listArchive(&archive);
|
|
|
|
for (QVector< Lib7z::File >::const_iterator fileIt = files.begin();
|
|
|
|
fileIt != files.end(); ++fileIt) {
|
|
|
|
componentSize += fileIt->uncompressedSize;
|
|
|
|
}
|
|
|
|
} else {
|
2012-02-15 13:39:53 +01:00
|
|
|
// otherwise just add its size
|
2012-11-07 14:07:05 +01:00
|
|
|
const quint64 size = fi.size();
|
|
|
|
componentSize += size;
|
|
|
|
compressedComponentSize += size;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
} catch(...) {
|
|
|
|
// ignore, that's just about the sizes - and size doesn't matter, you know?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-27 15:51:34 +02:00
|
|
|
QDomElement fileElement = doc.createElement(QLatin1String("UpdateFile"));
|
|
|
|
fileElement.setAttribute(QLatin1String("UncompressedSize"), componentSize);
|
|
|
|
fileElement.setAttribute(QLatin1String("CompressedSize"), compressedComponentSize);
|
|
|
|
update.appendChild(fileElement);
|
2011-02-21 16:30:31 +01:00
|
|
|
|
|
|
|
root.appendChild(update);
|
|
|
|
|
|
|
|
if (!QDir(metapath).mkpath(it->name))
|
2012-09-27 17:49:31 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Could not create directory \"%1\".").arg(it->name));
|
2011-02-21 16:30:31 +01:00
|
|
|
|
|
|
|
// copy scripts
|
2012-03-15 14:53:47 +01:00
|
|
|
const QString script = package.firstChildElement(QLatin1String("Script")).text();
|
2011-02-21 16:30:31 +01:00
|
|
|
if (!script.isEmpty()) {
|
2012-03-27 13:55:25 +02:00
|
|
|
const QString fromLocation(QString::fromLatin1("%1/meta/%2").arg(it->directory, script));
|
2011-11-08 14:36:12 +01:00
|
|
|
|
|
|
|
QString scriptContent;
|
2012-03-27 13:55:25 +02:00
|
|
|
QFile scriptFile(fromLocation);
|
2011-11-08 14:36:12 +01:00
|
|
|
if (scriptFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
|
|
QTextStream in(&scriptFile);
|
|
|
|
scriptContent = in.readAll();
|
|
|
|
}
|
2012-03-27 13:55:25 +02:00
|
|
|
static QScriptEngine testScriptEngine;
|
|
|
|
testScriptEngine.evaluate(scriptContent, scriptFile.fileName());
|
|
|
|
if (testScriptEngine.hasUncaughtException()) {
|
2012-09-27 17:49:31 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Exception while loading the component script: \"%1\"")
|
2012-03-27 13:55:25 +02:00
|
|
|
.arg(QInstaller::uncaughtExceptionString(&testScriptEngine, scriptFile.fileName())));
|
|
|
|
}
|
2011-11-08 14:36:12 +01:00
|
|
|
|
2011-11-17 22:44:56 +01:00
|
|
|
// added the xml tag RequiresAdminRights to the xml if somewhere addElevatedOperation is used
|
2012-03-15 14:53:47 +01:00
|
|
|
if (scriptContent.contains(QLatin1String("addElevatedOperation"))) {
|
|
|
|
QDomElement requiresAdminRightsElement =
|
|
|
|
doc.createElement(QLatin1String("RequiresAdminRights"));
|
|
|
|
requiresAdminRightsElement.appendChild(doc.createTextNode(QLatin1String("true")));
|
2011-11-08 14:36:12 +01:00
|
|
|
}
|
|
|
|
|
2012-02-21 10:58:27 +01:00
|
|
|
qDebug() << "\tCopying associated script" << script << "into the meta package...";
|
2011-08-24 14:35:28 +02:00
|
|
|
QString toLocation(QString::fromLatin1("%1/%2/%3").arg(metapath, it->name, script));
|
2012-03-27 13:55:25 +02:00
|
|
|
if (!scriptFile.copy(toLocation)) {
|
2012-01-16 23:42:54 +01:00
|
|
|
qDebug() << "failed!";
|
2012-09-27 17:49:31 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Could not copy the script \"%1\" to its target location \"%2\".")
|
2011-08-24 14:35:28 +02:00
|
|
|
.arg(fromLocation, toLocation));
|
2011-02-21 16:30:31 +01:00
|
|
|
} else {
|
2012-02-21 10:58:27 +01:00
|
|
|
qDebug() << "\tdone.";
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// copy user interfaces
|
2012-03-15 14:53:47 +01:00
|
|
|
const QDomNodeList uiNodes = package.firstChildElement(QLatin1String("UserInterfaces")).childNodes();
|
2011-02-21 16:30:31 +01:00
|
|
|
QStringList userinterfaces;
|
|
|
|
for (int i = 0; i < uiNodes.count(); ++i) {
|
|
|
|
const QDomNode node = uiNodes.at(i);
|
2011-11-19 13:01:27 +01:00
|
|
|
if (node.nodeName() != QLatin1String("UserInterface"))
|
2011-02-21 16:30:31 +01:00
|
|
|
continue;
|
|
|
|
|
|
|
|
const QDir dir(QString::fromLatin1("%1/meta").arg(it->directory));
|
|
|
|
const QStringList uis = dir.entryList(QStringList(node.toElement().text()), QDir::Files);
|
|
|
|
if (uis.isEmpty()) {
|
2012-09-27 17:49:31 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Couldn't find any user interface matching %1 while "
|
2012-03-13 17:53:03 +01:00
|
|
|
"copying user interfaces of %2.").arg(node.toElement().text(), it->name));
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
for (QStringList::const_iterator ui = uis.begin(); ui != uis.end(); ++ui) {
|
2012-03-20 16:35:27 +01:00
|
|
|
qDebug() << "\tCopying associated user interface" << *ui << "into the meta package...";
|
2011-02-21 16:30:31 +01:00
|
|
|
userinterfaces.push_back(*ui);
|
|
|
|
if (!QFile::copy(QString::fromLatin1("%1/meta/%2").arg(it->directory, *ui),
|
|
|
|
QString::fromLatin1("%1/%2/%3").arg(metapath, it->name, *ui))) {
|
2012-01-16 23:42:54 +01:00
|
|
|
qDebug() << "failed!";
|
2012-09-27 17:49:31 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Could not copy the UI file %1 to its target "
|
2012-03-13 17:53:03 +01:00
|
|
|
"location %2.").arg(*ui, it->name));
|
2011-02-21 16:30:31 +01:00
|
|
|
} else {
|
2012-01-16 23:42:54 +01:00
|
|
|
qDebug() << "done";
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!userinterfaces.isEmpty()) {
|
2011-11-19 13:01:27 +01:00
|
|
|
update.appendChild(doc.createElement(QLatin1String("UserInterfaces")))
|
2011-02-21 16:30:31 +01:00
|
|
|
.appendChild(doc.createTextNode(userinterfaces.join(QChar::fromLatin1(','))));
|
|
|
|
}
|
|
|
|
|
|
|
|
// copy translations
|
2012-03-15 14:53:47 +01:00
|
|
|
const QDomNodeList qmNodes = package.firstChildElement(QLatin1String("Translations")).childNodes();
|
2011-02-21 16:30:31 +01:00
|
|
|
QStringList translations;
|
2012-03-07 16:47:47 +01:00
|
|
|
if (!qApp->arguments().contains(QString::fromLatin1("--ignore-translations"))) {
|
|
|
|
for (int i = 0; i < qmNodes.count(); ++i) {
|
|
|
|
const QDomNode node = qmNodes.at(i);
|
|
|
|
if (node.nodeName() != QLatin1String("Translation"))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
const QDir dir(QString::fromLatin1("%1/meta").arg(it->directory));
|
|
|
|
const QStringList qms = dir.entryList(QStringList(node.toElement().text()), QDir::Files);
|
|
|
|
if (qms.isEmpty()) {
|
2012-09-27 17:49:31 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Could not find any translation file matching \"%1\" "
|
|
|
|
"while copying translations of \"%2\".").arg(node.toElement().text(), it->name));
|
2012-03-07 16:47:47 +01:00
|
|
|
}
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2012-03-07 16:47:47 +01:00
|
|
|
for (QStringList::const_iterator qm = qms.begin(); qm != qms.end(); ++qm) {
|
2012-03-20 16:35:27 +01:00
|
|
|
qDebug() << "\tCopying associated translation" << *qm << "into the meta package...";
|
2012-03-07 16:47:47 +01:00
|
|
|
translations.push_back(*qm);
|
|
|
|
if (!QFile::copy(QString::fromLatin1("%1/meta/%2").arg(it->directory, *qm),
|
|
|
|
QString::fromLatin1("%1/%2/%3").arg(metapath, it->name, *qm))) {
|
|
|
|
qDebug() << "failed!";
|
2012-09-27 17:49:31 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Could not copy the translation \"%1\" to its "
|
|
|
|
"target location \"%2\".").arg(*qm, it->name));
|
2012-03-07 16:47:47 +01:00
|
|
|
} else {
|
|
|
|
qDebug() << "done";
|
|
|
|
}
|
|
|
|
}
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
2012-03-07 16:47:47 +01:00
|
|
|
if (!translations.isEmpty()) {
|
|
|
|
update.appendChild(doc.createElement(QLatin1String("Translations")))
|
|
|
|
.appendChild(doc.createTextNode(translations.join(QChar::fromLatin1(','))));
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// copy license files
|
2012-03-15 14:53:47 +01:00
|
|
|
const QDomNodeList licenseNodes = package.firstChildElement(QLatin1String("Licenses")).childNodes();
|
2011-02-21 16:30:31 +01:00
|
|
|
for (int i = 0; i < licenseNodes.count(); ++i) {
|
|
|
|
const QDomNode licenseNode = licenseNodes.at(i);
|
|
|
|
if (licenseNode.nodeName() == QLatin1String("License")) {
|
|
|
|
const QString &licenseFile =
|
|
|
|
licenseNode.toElement().attributeNode(QLatin1String("file")).value();
|
|
|
|
const QString &sourceFile =
|
|
|
|
QString::fromLatin1("%1/meta/%2").arg(it->directory).arg(licenseFile);
|
|
|
|
if (!QFile::exists(sourceFile)) {
|
2012-09-27 17:49:31 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Could not find any license matching \"%1\" while "
|
2012-02-09 12:25:23 +01:00
|
|
|
"copying license files of %2.").arg(licenseFile, it->name));
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
2012-03-20 16:35:27 +01:00
|
|
|
qDebug() << "\tCopying associated license file" << licenseFile << "into the meta package...";
|
2011-02-21 16:30:31 +01:00
|
|
|
if (!QFile::copy(sourceFile, QString::fromLatin1("%1/%2/%3")
|
|
|
|
.arg(metapath, it->name, licenseFile))) {
|
2012-01-16 23:42:54 +01:00
|
|
|
qDebug() << "failed!";
|
2012-09-27 17:49:31 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Could not copy the license file \"%1\" to its "
|
2012-02-09 12:25:23 +01:00
|
|
|
"target location %2.").arg(licenseFile, it->name));
|
2011-02-21 16:30:31 +01:00
|
|
|
} else {
|
2012-01-16 23:42:54 +01:00
|
|
|
qDebug() << "done.";
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
2012-02-15 15:26:45 +01:00
|
|
|
|
|
|
|
// Translated License files
|
|
|
|
for (int j = 0; j < translations.size(); ++j) {
|
|
|
|
QFileInfo translationFile(translations.at(j));
|
|
|
|
QFileInfo untranslated(licenseFile);
|
|
|
|
const QString &translatedLicenseFile =
|
|
|
|
QString::fromLatin1("%2_%3.%4").arg(untranslated.baseName(),
|
2012-02-28 15:01:08 +01:00
|
|
|
translationFile.baseName(), untranslated.completeSuffix());
|
2012-02-15 15:26:45 +01:00
|
|
|
const QString &translatedSourceFile =
|
|
|
|
QString::fromLatin1("%1/meta/%2").arg(it->directory).arg(translatedLicenseFile);
|
|
|
|
if (!QFile::exists(translatedSourceFile)) {
|
|
|
|
qDebug() << "Could not find translated license file" << translatedSourceFile;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2012-02-28 15:01:08 +01:00
|
|
|
qDebug() << "\tCopying associated license file" << translatedLicenseFile
|
|
|
|
<< "into the meta package...";
|
2012-02-15 15:26:45 +01:00
|
|
|
|
|
|
|
if (!QFile::copy(translatedSourceFile, QString::fromLatin1("%1/%2/%3")
|
|
|
|
.arg(metapath, it->name, translatedLicenseFile))) {
|
|
|
|
qDebug() << "\tfailed!";
|
|
|
|
} else {
|
|
|
|
qDebug() << "\tdone.";
|
|
|
|
}
|
|
|
|
}
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (licenseNodes.count() > 0)
|
2012-03-15 14:53:47 +01:00
|
|
|
update.appendChild(package.firstChildElement(QLatin1String("Licenses")).cloneNode());
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
doc.appendChild(root);
|
|
|
|
|
2012-03-15 14:53:47 +01:00
|
|
|
const QString updatesXmlFile = QFileInfo(metapath, QLatin1String("Updates.xml")).absoluteFilePath();
|
2011-02-21 16:30:31 +01:00
|
|
|
QFile updatesXml(updatesXmlFile);
|
|
|
|
|
2012-03-13 17:53:03 +01:00
|
|
|
QInstaller::openForWrite(&updatesXml, updatesXmlFile);
|
|
|
|
QInstaller::blockingWrite(&updatesXml, doc.toByteArray());
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
2012-03-13 17:53:03 +01:00
|
|
|
PackageInfoVector QInstallerTools::createListOfPackages(const QString &packagesDirectory,
|
2012-03-12 19:02:53 +01:00
|
|
|
const QStringList &filteredPackages, FilterType filterType)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2012-03-12 19:02:53 +01:00
|
|
|
qDebug() << "Collecting information about available packages...";
|
|
|
|
|
|
|
|
bool ignoreInvalidPackages = qApp->arguments().contains(QString::fromLatin1("--ignore-invalid-packages"));
|
|
|
|
|
|
|
|
PackageInfoVector dict;
|
|
|
|
const QFileInfoList entries = QDir(packagesDirectory)
|
|
|
|
.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
|
|
|
|
for (QFileInfoList::const_iterator it = entries.begin(); it != entries.end(); ++it) {
|
|
|
|
if (filterType == Exclude) {
|
|
|
|
if (filteredPackages.contains(it->fileName()))
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
if (!filteredPackages.contains(it->fileName()))
|
|
|
|
continue;
|
|
|
|
}
|
2012-09-27 17:49:31 +02:00
|
|
|
qDebug() << QString::fromLatin1("\tfound subdirectory \"%1\"").arg(it->fileName());
|
2012-03-12 19:02:53 +01:00
|
|
|
// because the filter is QDir::Dirs - filename means the name of the subdirectory
|
|
|
|
if (it->fileName().contains(QLatin1Char('-'))) {
|
|
|
|
if (ignoreInvalidPackages)
|
|
|
|
continue;
|
2012-09-27 17:49:31 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Component \"%1\" can't contain '-'. This is not allowed, because "
|
2012-03-13 17:53:03 +01:00
|
|
|
"it is used as the separator between the component name and the version number internally.")
|
|
|
|
.arg(it->fileName()));
|
2011-10-21 13:13:33 +02:00
|
|
|
}
|
2011-10-20 14:41:43 +02:00
|
|
|
|
2012-03-12 19:02:53 +01:00
|
|
|
QFile file(QString::fromLatin1("%1/meta/package.xml").arg(it->filePath()));
|
2012-09-27 15:50:36 +02:00
|
|
|
QFileInfo fileInfo(file);
|
|
|
|
if (!fileInfo.exists()) {
|
2012-03-12 19:02:53 +01:00
|
|
|
if (ignoreInvalidPackages)
|
|
|
|
continue;
|
2012-09-27 17:49:31 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Component \"%1\" does not contain a package "
|
|
|
|
"description (meta/package.xml is missing).").arg(it->fileName()));
|
2012-03-12 19:02:53 +01:00
|
|
|
}
|
2011-10-20 14:41:43 +02:00
|
|
|
|
2012-03-12 19:02:53 +01:00
|
|
|
file.open(QIODevice::ReadOnly);
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2012-03-12 19:02:53 +01:00
|
|
|
QDomDocument doc;
|
|
|
|
QString error;
|
|
|
|
int errorLine = 0;
|
|
|
|
int errorColumn = 0;
|
|
|
|
if (!doc.setContent(&file, &error, &errorLine, &errorColumn)) {
|
|
|
|
if (ignoreInvalidPackages)
|
|
|
|
continue;
|
2012-09-27 17:49:31 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Component package description in \"%1\" is invalid. "
|
2012-09-27 15:50:36 +02:00
|
|
|
"Error at line: %2, column: %3 -> %4").arg(fileInfo.absoluteFilePath(), QString::number(errorLine),
|
2012-03-12 19:02:53 +01:00
|
|
|
QString::number(errorColumn), error));
|
2012-01-16 23:42:54 +01:00
|
|
|
}
|
2012-03-12 19:02:53 +01:00
|
|
|
|
|
|
|
const QString name = doc.firstChildElement(QLatin1String("Package"))
|
|
|
|
.firstChildElement(QLatin1String("Name")).text();
|
2012-09-27 15:50:36 +02:00
|
|
|
if (!name.isEmpty() && name != it->fileName()) {
|
2012-09-27 17:49:31 +02:00
|
|
|
qWarning() << QString::fromLatin1("The <Name> tag in the \"%1\" is ignored - the installer uses the "
|
2012-09-27 15:50:36 +02:00
|
|
|
"path element right before the \"meta\" (\"%2\").").arg(fileInfo.absoluteFilePath(), it->fileName());
|
2012-03-12 19:02:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
PackageInfo info;
|
2012-09-27 15:50:36 +02:00
|
|
|
info.name = it->fileName();
|
2012-03-12 19:02:53 +01:00
|
|
|
info.version = doc.firstChildElement(QLatin1String("Package")).
|
|
|
|
firstChildElement(QLatin1String("Version")).text();
|
|
|
|
if (!QRegExp(QLatin1String("[0-9]+((\\.|-)[0-9]+)*")).exactMatch(info.version)) {
|
|
|
|
if (ignoreInvalidPackages)
|
|
|
|
continue;
|
2012-12-12 16:02:18 +01:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Component version for %1 is invalid! <Version>%2</Version>")
|
2012-09-27 15:50:36 +02:00
|
|
|
.arg(fileInfo.absoluteFilePath(), info.version));
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
2012-03-12 19:02:53 +01:00
|
|
|
info.dependencies = doc.firstChildElement(QLatin1String("Package")).
|
2012-04-27 14:12:41 +02:00
|
|
|
firstChildElement(QLatin1String("Dependencies")).text().split(QInstaller::scCommaRegExp,
|
2012-03-12 19:02:53 +01:00
|
|
|
QString::SkipEmptyParts);
|
|
|
|
info.directory = it->filePath();
|
|
|
|
dict.push_back(info);
|
|
|
|
|
|
|
|
qDebug() << QString::fromLatin1("\t- it provides the package %1 - %2").arg(name, info.version);
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
2012-03-12 19:02:53 +01:00
|
|
|
if (dict.isEmpty())
|
|
|
|
qDebug() << "No available packages found at the specified location.";
|
|
|
|
|
|
|
|
return dict;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
2012-05-03 13:15:26 +02:00
|
|
|
QHash<QString, QString> QInstallerTools::buildPathToVersionMapping(const PackageInfoVector &info)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2012-05-03 13:15:26 +02:00
|
|
|
QHash<QString, QString> map;
|
2011-11-17 22:44:56 +01:00
|
|
|
foreach (const PackageInfo &inf, info)
|
2011-02-21 16:30:31 +01:00
|
|
|
map[inf.name] = inf.version;
|
|
|
|
return map;
|
|
|
|
}
|
|
|
|
|
2011-11-17 22:44:56 +01:00
|
|
|
static void writeSHA1ToNodeWithName(QDomDocument &doc, QDomNodeList &list, const QByteArray &sha1sum,
|
|
|
|
const QString &nodename)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2012-01-16 23:42:54 +01:00
|
|
|
qDebug() << "searching sha1sum node for" << nodename;
|
2011-02-21 16:30:31 +01:00
|
|
|
for (int i = 0; i < list.size(); ++i) {
|
|
|
|
QDomNode curNode = list.at(i);
|
|
|
|
QDomNode nameTag = curNode.firstChildElement(QLatin1String("Name"));
|
|
|
|
if (!nameTag.isNull() && nameTag.toElement().text() == nodename) {
|
|
|
|
QDomNode sha1Node = doc.createElement(QLatin1String("SHA1"));
|
|
|
|
sha1Node.appendChild(doc.createTextNode(QString::fromLatin1(sha1sum.toHex().constData())));
|
|
|
|
curNode.appendChild(sha1Node);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-13 17:53:03 +01:00
|
|
|
void QInstallerTools::compressMetaDirectories(const QString &repoDir, const QString &baseDir,
|
2012-05-03 13:15:26 +02:00
|
|
|
const QHash<QString, QString> &versionMapping)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
|
|
|
QDomDocument doc;
|
|
|
|
QDomElement root;
|
|
|
|
// use existing Updates.xml, if any
|
|
|
|
QFile existingUpdatesXml(QFileInfo(QDir(repoDir), QLatin1String("Updates.xml")).absoluteFilePath());
|
|
|
|
if (!existingUpdatesXml.open(QIODevice::ReadOnly) || !doc.setContent(&existingUpdatesXml)) {
|
2012-01-16 23:42:54 +01:00
|
|
|
qDebug() << "Could not find Updates.xml";
|
2011-02-21 16:30:31 +01:00
|
|
|
} else {
|
|
|
|
root = doc.documentElement();
|
|
|
|
}
|
|
|
|
existingUpdatesXml.close();
|
|
|
|
|
|
|
|
QDir dir(repoDir);
|
|
|
|
const QStringList sub = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
|
|
|
|
QDomNodeList elements = doc.elementsByTagName(QLatin1String("PackageUpdate"));
|
2011-11-17 22:44:56 +01:00
|
|
|
foreach (const QString &i, sub) {
|
2011-02-21 16:30:31 +01:00
|
|
|
QDir sd(dir);
|
|
|
|
sd.cd(i);
|
|
|
|
const QString path = QString(i).remove(baseDir);
|
|
|
|
const QString versionPrefix = versionMapping[path];
|
|
|
|
if (path.isNull())
|
|
|
|
continue;
|
|
|
|
const QString absPath = sd.absolutePath();
|
|
|
|
const QString fn = QLatin1String(versionPrefix.toLatin1() + "meta.7z");
|
|
|
|
const QString tmpTarget = repoDir + QLatin1String("/") +fn;
|
2012-05-14 15:32:58 +02:00
|
|
|
compressPaths(QStringList() << absPath, tmpTarget);
|
2012-03-06 16:58:44 +01:00
|
|
|
|
|
|
|
// remove the files that got compressed
|
|
|
|
QInstaller::removeFiles(absPath, true);
|
|
|
|
|
2011-02-21 16:30:31 +01:00
|
|
|
QFile tmp(tmpTarget);
|
|
|
|
tmp.open(QFile::ReadOnly);
|
2012-09-28 14:46:17 +02:00
|
|
|
const QByteArray sha1Sum = QInstaller::calculateHash(&tmp, QCryptographicHash::Sha1);
|
2011-02-21 16:30:31 +01:00
|
|
|
writeSHA1ToNodeWithName(doc, elements, sha1Sum, path);
|
|
|
|
const QString finalTarget = absPath + QLatin1String("/") + fn;
|
|
|
|
if (!tmp.rename(finalTarget))
|
2012-09-27 17:49:31 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Could not move %1 to %2").arg(tmpTarget, finalTarget));
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
2012-02-28 16:11:44 +01:00
|
|
|
|
2012-03-13 17:53:03 +01:00
|
|
|
QInstaller::openForWrite(&existingUpdatesXml, existingUpdatesXml.fileName());
|
|
|
|
QInstaller::blockingWrite(&existingUpdatesXml, doc.toByteArray());
|
2011-02-21 16:30:31 +01:00
|
|
|
existingUpdatesXml.close();
|
|
|
|
}
|
|
|
|
|
2012-03-13 17:53:03 +01:00
|
|
|
void QInstallerTools::copyComponentData(const QString &packageDir, const QString &repoDir,
|
|
|
|
PackageInfoVector &infos)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2012-02-28 17:50:35 +01:00
|
|
|
for (int i = 0; i < infos.count(); ++i) {
|
|
|
|
const PackageInfo info = infos.at(i);
|
|
|
|
const QString name = info.name;
|
|
|
|
qDebug() << "Copying component data for" << name;
|
2012-08-21 12:10:07 +02:00
|
|
|
|
|
|
|
const QString namedRepoDir = QString::fromLatin1("%1/%2").arg(repoDir, name);
|
|
|
|
if (!QDir().mkpath(namedRepoDir)) {
|
2012-09-27 17:49:31 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Could not create repository folder for component %1")
|
2012-02-28 17:50:35 +01:00
|
|
|
.arg(name));
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
2012-08-21 12:10:07 +02:00
|
|
|
QStringList compressedFiles;
|
|
|
|
QStringList filesToCompress;
|
|
|
|
const QDir dataDir(QString::fromLatin1("%1/%2/data").arg(packageDir, name));
|
|
|
|
foreach (const QString &entry, dataDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::Files)) {
|
2012-02-28 17:50:35 +01:00
|
|
|
QFileInfo fileInfo(dataDir.absoluteFilePath(entry));
|
2012-11-07 14:07:05 +01:00
|
|
|
if (fileInfo.isFile() && !fileInfo.isSymLink()) {
|
2012-08-21 12:10:07 +02:00
|
|
|
const QString absoluteEntryFilePath = dataDir.absoluteFilePath(entry);
|
|
|
|
if (Lib7z::isSupportedArchive(absoluteEntryFilePath)) {
|
|
|
|
QFile tmp(absoluteEntryFilePath);
|
|
|
|
QString target = QString::fromLatin1("%1/%3%2").arg(namedRepoDir, entry, info.version);
|
|
|
|
qDebug() << QString::fromLatin1("Copying archive from %1 to %2").arg(tmp.fileName(),
|
|
|
|
target);
|
|
|
|
if (!tmp.copy(target)) {
|
2012-09-27 17:49:31 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Could not copy %1 to %2: %3").arg(tmp.fileName(),
|
2012-08-21 12:10:07 +02:00
|
|
|
target, tmp.errorString()));
|
|
|
|
}
|
|
|
|
compressedFiles.append(target);
|
|
|
|
} else {
|
|
|
|
filesToCompress.append(absoluteEntryFilePath);
|
2012-02-28 17:50:35 +01:00
|
|
|
}
|
|
|
|
} else if (fileInfo.isDir()) {
|
|
|
|
qDebug() << "Compressing data directory" << entry;
|
2012-08-21 12:10:07 +02:00
|
|
|
QString target = QString::fromLatin1("%1/%3%2.7z").arg(namedRepoDir, entry, info.version);
|
2012-05-14 15:32:58 +02:00
|
|
|
QInstallerTools::compressPaths(QStringList() << dataDir.absoluteFilePath(entry), target);
|
2012-08-21 12:10:07 +02:00
|
|
|
compressedFiles.append(target);
|
2012-11-07 14:07:05 +01:00
|
|
|
} else if (fileInfo.isSymLink()) {
|
|
|
|
filesToCompress.append(dataDir.absoluteFilePath(entry));
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
2012-08-21 12:10:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!filesToCompress.isEmpty()) {
|
|
|
|
qDebug() << "Compressing files found in data directory:" << filesToCompress;
|
|
|
|
QString target = QString::fromLatin1("%1/%3%2").arg(namedRepoDir, QLatin1String("content.7z"),
|
|
|
|
info.version);
|
|
|
|
QInstallerTools::compressPaths(filesToCompress, target);
|
|
|
|
compressedFiles.append(target);
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach (const QString &target, compressedFiles) {
|
2012-02-28 17:50:35 +01:00
|
|
|
infos[i].copiedArchives.append(target);
|
|
|
|
|
2011-02-21 16:30:31 +01:00
|
|
|
QFile archiveFile(target);
|
2012-02-28 17:50:35 +01:00
|
|
|
QFile archiveHashFile(archiveFile.fileName() + QLatin1String(".sha1"));
|
2011-02-21 16:30:31 +01:00
|
|
|
|
2012-02-28 17:50:35 +01:00
|
|
|
qDebug() << "Hash is stored in" << archiveHashFile.fileName();
|
|
|
|
qDebug() << "Creating hash of archive" << archiveFile.fileName();
|
2011-02-21 16:30:31 +01:00
|
|
|
|
|
|
|
try {
|
2012-03-13 17:53:03 +01:00
|
|
|
QInstaller::openForRead(&archiveFile, archiveFile.fileName());
|
2012-09-28 14:46:17 +02:00
|
|
|
const QByteArray hashOfArchiveData = QInstaller::calculateHash(&archiveFile,
|
|
|
|
QCryptographicHash::Sha1).toHex();
|
2011-02-21 16:30:31 +01:00
|
|
|
archiveFile.close();
|
2012-02-28 17:50:35 +01:00
|
|
|
|
2012-03-13 17:53:03 +01:00
|
|
|
QInstaller::openForWrite(&archiveHashFile, archiveHashFile.fileName());
|
2011-02-21 16:30:31 +01:00
|
|
|
archiveHashFile.write(hashOfArchiveData);
|
2012-02-28 17:50:35 +01:00
|
|
|
qDebug() << "Generated sha1 hash:" << hashOfArchiveData;
|
|
|
|
infos[i].copiedArchives.append(archiveHashFile.fileName());
|
2011-02-21 16:30:31 +01:00
|
|
|
archiveHashFile.close();
|
2012-03-13 17:53:03 +01:00
|
|
|
} catch (const QInstaller::Error &/*e*/) {
|
2011-02-21 16:30:31 +01:00
|
|
|
archiveFile.close();
|
2012-02-28 17:50:35 +01:00
|
|
|
archiveHashFile.close();
|
2011-02-21 16:30:31 +01:00
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|