installer-framework/tools/common/repositorygen.cpp

621 lines
28 KiB
C++
Raw Normal View History

2011-02-21 16:30:31 +01:00
/**************************************************************************
**
** This file is part of Installer Framework
2011-02-21 16:30:31 +01:00
**
** Copyright (c) 2011-2012 Nokia Corporation and/or its subsidiary(-ies).
2011-02-21 16:30:31 +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
** 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
**
** 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
** Nokia at qt-info@nokia.com.
2011-02-21 16:30:31 +01:00
**
**************************************************************************/
#include "repositorygen.h"
#include <fileutils.h>
#include <errors.h>
#include <lib7z_facade.h>
#include <settings.h>
2011-02-21 16:30:31 +01:00
#include <kdupdater.h>
#include <QtCore/QCryptographicHash>
#include <QtCore/QDirIterator>
2011-02-21 16:30:31 +01:00
#include <QtXml/QDomDocument>
2011-02-21 16:30:31 +01:00
#include <iostream>
using namespace QInstallerTools;
void QInstallerTools::printRepositoryGenOptions()
{
std::cout << " -c|--config dir The directory containing the installer configuration" << std::endl;
std::cout << " -p|--packages dir The directory containing the available packages." << std::endl;
std::cout << " Defaults to the current working directory." << std::endl;
std::cout << " -e|--exclude p1,...,pn Exclude the given packages." << std::endl;
std::cout << " -i|--include p1,...,pn Include the given packages and their dependencies" << std::endl;
std::cout << " from the repository." << std::endl;
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;
}
void QInstallerTools::compressDirectory(const QStringList &paths, const QString &archivePath)
2011-02-21 16:30:31 +01:00
{
foreach (const QString &path, paths) {
if (!QFileInfo(path).exists())
throw QInstaller::Error(QObject::tr("Folder %1 does not exist.").arg(path));
}
2011-02-21 16:30:31 +01:00
QFile archive(archivePath);
QInstaller::openForWrite(&archive, archivePath);
Lib7z::createArchive(&archive, paths);
2011-02-21 16:30:31 +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);
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;
compressDirectory(QStringList() << absPath, tmpTarget);
2011-02-21 16:30:31 +01:00
QFile tmp(tmpTarget);
const QString finalTarget = absPath + QLatin1String("/") + fn;
if (!tmp.rename(finalTarget)) {
throw QInstaller::Error(QObject::tr("Could not move %1 to %2").arg(tmpTarget,
finalTarget));
}
}
}
void QInstallerTools::generateMetaDataDirectory(const QString &outDir, const QString &dataDir,
const PackageInfoVector &packages, const QString &appName, const QString &appVersion,
const QString &redirectUpdateUrl)
2011-02-21 16:30:31 +01:00
{
QString metapath = outDir;
2011-02-21 16:30:31 +01:00
if (QFileInfo(metapath).isRelative())
metapath = QDir::cleanPath(QDir::current().absoluteFilePath(metapath));
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)) {
root = doc.createElement(QLatin1String("Updates"));
root.appendChild(doc.createElement(QLatin1String("ApplicationName"))).appendChild(
2011-02-21 16:30:31 +01:00
doc.createTextNode(appName));
root.appendChild(doc.createElement(QLatin1String("ApplicationVersion"))).appendChild(
2011-02-21 16:30:31 +01:00
doc.createTextNode(appVersion));
root.appendChild(doc.createElement(QLatin1String("Checksum"))).appendChild(
2011-02-21 16:30:31 +01:00
doc.createTextNode(QLatin1String("true")));
if (!redirectUpdateUrl.isEmpty()) {
root.appendChild(doc.createElement(QLatin1String("RedirectUpdateUrl"))).appendChild(
doc.createTextNode(redirectUpdateUrl));
}
2011-02-21 16:30:31 +01:00
} else {
root = doc.documentElement();
}
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);
qDebug() << QString::fromLatin1("\tGenerating meta data for package %1 using %2.").arg(
it->name, packageXmlPath);
2011-02-21 16:30:31 +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);
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)) {
throw QInstaller::Error(QObject::tr("Could not parse %1: line: %2, column: %3: %4 (%5)")
.arg(packageXmlPath, QString::number(line), QString::number(col), errMsg, it->name));
2011-02-21 16:30:31 +01:00
}
const QDomNode package = packageXml.firstChildElement(QLatin1String("Package"));
2011-02-21 16:30:31 +01:00
QDomElement update = doc.createElement(QLatin1String("PackageUpdate"));
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);
// just skip the comments...
if (node.isComment())
continue;
const QString key = node.nodeName();
if (key == QLatin1String("UserInterfaces"))
2011-02-21 16:30:31 +01:00
continue;
if (key == QLatin1String("Translations"))
2011-02-21 16:30:31 +01:00
continue;
if (key == QLatin1String("Licenses"))
2011-02-21 16:30:31 +01:00
continue;
const QString value = node.toElement().text();
QDomElement element = doc.createElement(key);
for (int i = 0; i < node.attributes().size(); i++) {
element.setAttribute(node.attributes().item(i).toAttr().name(),
node.attributes().item(i).toAttr().value());
}
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;
const QString cmpDataDir = QString::fromLatin1("%1/%2").arg(dataDir, it->name);
const QFileInfoList entries = !QDir(cmpDataDir + QLatin1String("/data")).exists()
? QDir(cmpDataDir).entryInfoList(QDir::Files | QDir::NoDotAndDotDot)
: QDir(cmpDataDir + QLatin1String("/data")).entryInfoList(QDir::Files
| QDir::Dirs | QDir::NoDotAndDotDot);
2011-02-21 16:30:31 +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()) {
componentSize += QFile(recursDirIt.next()).size();
compressedComponentSize += QFile(recursDirIt.next()).size();
}
} else if (Lib7z::isSupportedArchive(fi.filePath())) {
// 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 {
// otherwise just add its size
2011-02-21 16:30:31 +01:00
componentSize += fi.size();
compressedComponentSize += fi.size();
}
} catch(...) {
// ignore, that's just about the sizes - and size doesn't matter, you know?
}
}
// add fake update files
const QStringList platforms = QStringList() << QLatin1String("Windows") << QLatin1String("MacOSX")
<< QLatin1String("Linux");
foreach (const QString &platform, platforms) {
QDomElement file = doc.createElement(QLatin1String("UpdateFile"));
file.setAttribute(QLatin1String("OS"), platform);
file.setAttribute(QLatin1String("UncompressedSize"), componentSize);
file.setAttribute(QLatin1String("CompressedSize"), compressedComponentSize);
2011-02-21 16:30:31 +01:00
file.appendChild(doc.createTextNode(QLatin1String("(null)")));
update.appendChild(file);
}
root.appendChild(update);
if (!QDir(metapath).mkpath(it->name))
throw QInstaller::Error(QObject::tr("Could not create directory %1.").arg(it->name));
2011-02-21 16:30:31 +01:00
// copy scripts
const QString script = package.firstChildElement(QLatin1String("Script")).text();
2011-02-21 16:30:31 +01:00
if (!script.isEmpty()) {
QFile scriptFile(script);
QString scriptContent;
if (scriptFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&scriptFile);
scriptContent = in.readAll();
}
// added the xml tag RequiresAdminRights to the xml if somewhere addElevatedOperation is used
if (scriptContent.contains(QLatin1String("addElevatedOperation"))) {
QDomElement requiresAdminRightsElement =
doc.createElement(QLatin1String("RequiresAdminRights"));
requiresAdminRightsElement.appendChild(doc.createTextNode(QLatin1String("true")));
}
qDebug() << "\tCopying associated script" << script << "into the meta package...";
QString fromLocation(QString::fromLatin1("%1/meta/%2").arg(it->directory, script));
QString toLocation(QString::fromLatin1("%1/%2/%3").arg(metapath, it->name, script));
if (!QFile::copy(fromLocation, toLocation)) {
qDebug() << "failed!";
throw QInstaller::Error(QObject::tr("Could not copy the script %1 to its target location %2.")
.arg(fromLocation, toLocation));
2011-02-21 16:30:31 +01:00
} else {
qDebug() << "\tdone.";
2011-02-21 16:30:31 +01:00
}
}
// copy user interfaces
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);
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()) {
throw QInstaller::Error(QObject::tr("Couldn't find any user interface matching %1 while "
"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) {
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))) {
qDebug() << "failed!";
throw QInstaller::Error(QObject::tr("Could not copy the UI file %1 to its target "
"location %2.").arg(*ui, it->name));
2011-02-21 16:30:31 +01:00
} else {
qDebug() << "done";
2011-02-21 16:30:31 +01:00
}
}
}
if (!userinterfaces.isEmpty()) {
update.appendChild(doc.createElement(QLatin1String("UserInterfaces")))
2011-02-21 16:30:31 +01:00
.appendChild(doc.createTextNode(userinterfaces.join(QChar::fromLatin1(','))));
}
// copy translations
const QDomNodeList qmNodes = package.firstChildElement(QLatin1String("Translations")).childNodes();
2011-02-21 16:30:31 +01:00
QStringList translations;
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()) {
throw QInstaller::Error(QObject::tr("Could not find any translation file matching %1 "
"while copying translations of %2.").arg(node.toElement().text(), it->name));
}
2011-02-21 16:30:31 +01:00
for (QStringList::const_iterator qm = qms.begin(); qm != qms.end(); ++qm) {
qDebug() << "\tCopying associated translation" << *qm << "into the meta package...";
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!";
throw QInstaller::Error(QObject::tr("Could not copy the translation %1 to its "
"target location %2.").arg(*qm, it->name));
} else {
qDebug() << "done";
}
}
2011-02-21 16:30:31 +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
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)) {
throw QInstaller::Error(QObject::tr("Could not find any license matching %1 while "
"copying license files of %2.").arg(licenseFile, it->name));
2011-02-21 16:30:31 +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))) {
qDebug() << "failed!";
throw QInstaller::Error(QObject::tr("Could not copy the license file %1 to its "
"target location %2.").arg(licenseFile, it->name));
2011-02-21 16:30:31 +01:00
} else {
qDebug() << "done.";
2011-02-21 16:30:31 +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(),
translationFile.baseName(), untranslated.completeSuffix());
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;
}
qDebug() << "\tCopying associated license file" << translatedLicenseFile
<< "into the meta package...";
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)
update.appendChild(package.firstChildElement(QLatin1String("Licenses")).cloneNode());
2011-02-21 16:30:31 +01:00
}
doc.appendChild(root);
const QString updatesXmlFile = QFileInfo(metapath, QLatin1String("Updates.xml")).absoluteFilePath();
2011-02-21 16:30:31 +01:00
QFile updatesXml(updatesXmlFile);
QInstaller::openForWrite(&updatesXml, updatesXmlFile);
QInstaller::blockingWrite(&updatesXml, doc.toByteArray());
2011-02-21 16:30:31 +01:00
}
PackageInfoVector QInstallerTools::createListOfPackages(const QString &packagesDirectory,
const QStringList &filteredPackages, FilterType filterType)
2011-02-21 16:30:31 +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;
}
qDebug() << QString::fromLatin1("\tfound subdirectory %1").arg(it->fileName());
// because the filter is QDir::Dirs - filename means the name of the subdirectory
if (it->fileName().contains(QLatin1Char('-'))) {
if (ignoreInvalidPackages)
continue;
throw QInstaller::Error(QObject::tr("Component %1 can't contain '-'. This is not allowed, because "
"it is used as the separator between the component name and the version number internally.")
.arg(it->fileName()));
}
QFile file(QString::fromLatin1("%1/meta/package.xml").arg(it->filePath()));
if (!file.exists()) {
if (ignoreInvalidPackages)
continue;
throw QInstaller::Error(QObject::tr("Component %1 does not contain a package "
"description(meta/package.xml is missing).").arg(it->fileName()));
}
file.open(QIODevice::ReadOnly);
2011-02-21 16:30:31 +01:00
QDomDocument doc;
QString error;
int errorLine = 0;
int errorColumn = 0;
if (!doc.setContent(&file, &error, &errorLine, &errorColumn)) {
if (ignoreInvalidPackages)
continue;
throw QInstaller::Error(QObject::tr("Component package description for %1 is invalid. "
"Error at line: %2, column: %3 -> %4").arg(it->fileName(), QString::number(errorLine),
QString::number(errorColumn), error));
}
const QString name = doc.firstChildElement(QLatin1String("Package"))
.firstChildElement(QLatin1String("Name")).text();
if (name != it->fileName()) {
if (ignoreInvalidPackages)
continue;
throw QInstaller::Error(QObject::tr("Component folder name must match component name: "
"%1 in %2/").arg(name, it->fileName()));
}
PackageInfo info;
info.name = name;
info.version = doc.firstChildElement(QLatin1String("Package")).
firstChildElement(QLatin1String("Version")).text();
if (!QRegExp(QLatin1String("[0-9]+((\\.|-)[0-9]+)*")).exactMatch(info.version)) {
if (ignoreInvalidPackages)
continue;
throw QInstaller::Error(QObject::tr("Component version for %1 is invalid! <Version>%2</version>")
.arg(it->fileName(), info.version));
2011-02-21 16:30:31 +01:00
}
info.dependencies = doc.firstChildElement(QLatin1String("Package")).
firstChildElement(QLatin1String("Dependencies")).text().split(QRegExp(QLatin1String("\\b(,|, )\\b")),
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
}
if (dict.isEmpty())
qDebug() << "No available packages found at the specified location.";
return dict;
2011-02-21 16:30:31 +01:00
}
QMap<QString, QString> QInstallerTools::buildPathToVersionMap(const PackageInfoVector &info)
2011-02-21 16:30:31 +01:00
{
QMap<QString, QString> map;
foreach (const PackageInfo &inf, info)
2011-02-21 16:30:31 +01:00
map[inf.name] = inf.version;
return map;
}
static void writeSHA1ToNodeWithName(QDomDocument &doc, QDomNodeList &list, const QByteArray &sha1sum,
const QString &nodename)
2011-02-21 16:30:31 +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);
}
}
}
void QInstallerTools::compressMetaDirectories(const QString &repoDir, const QString &baseDir,
const QMap<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)) {
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"));
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;
compressDirectory(QStringList() << absPath, tmpTarget);
// 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);
QByteArray fileToCheck = tmp.readAll();
QByteArray sha1Sum = QCryptographicHash::hash(fileToCheck, QCryptographicHash::Sha1);
writeSHA1ToNodeWithName(doc, elements, sha1Sum, path);
const QString finalTarget = absPath + QLatin1String("/") + fn;
if (!tmp.rename(finalTarget))
throw QInstaller::Error(QObject::tr("Could not move %1 to %2").arg(tmpTarget, finalTarget));
}
QInstaller::openForWrite(&existingUpdatesXml, existingUpdatesXml.fileName());
QInstaller::blockingWrite(&existingUpdatesXml, doc.toByteArray());
2011-02-21 16:30:31 +01:00
existingUpdatesXml.close();
}
void QInstallerTools::copyComponentData(const QString &packageDir, const QString &repoDir,
PackageInfoVector &infos)
2011-02-21 16:30:31 +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;
const QString dataDirPath = QString::fromLatin1("%1/%2/data").arg(packageDir, name);
2011-02-21 16:30:31 +01:00
const QDir dataDir(dataDirPath);
if (!QDir().mkpath(QString::fromLatin1("%1/%2").arg(repoDir, name))) {
throw QInstaller::Error(QObject::tr("Could not create repository folder for component %1")
.arg(name));
2011-02-21 16:30:31 +01:00
}
const QStringList entries = dataDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::Files);
foreach (const QString &entry, entries) {
QString target;
QFileInfo fileInfo(dataDir.absoluteFilePath(entry));
if (fileInfo.isFile()) {
target = QString::fromLatin1("%1/%2/%4%3").arg(repoDir, name, entry, info.version);
QFile tmp(dataDir.absoluteFilePath(entry));
qDebug() << QString::fromLatin1("Copying archive from %1 to %2").arg(tmp.fileName(), target);
QInstaller::openForRead(&tmp, tmp.fileName());
if (!tmp.copy(target)) {
throw QInstaller::Error(QObject::tr("Could not copy %1 to %2: %3").arg(tmp.fileName(),
target, tmp.errorString()));
}
} else if (fileInfo.isDir()) {
qDebug() << "Compressing data directory" << entry;
target = QString::fromLatin1("%1/%2/%4%3.7z").arg(repoDir, name, entry, info.version);
QInstallerTools::compressDirectory(QStringList() << dataDir.absoluteFilePath(entry), target);
} else {
continue;
2011-02-21 16:30:31 +01:00
}
infos[i].copiedArchives.append(target);
2011-02-21 16:30:31 +01:00
QFile archiveFile(target);
QFile archiveHashFile(archiveFile.fileName() + QLatin1String(".sha1"));
2011-02-21 16:30:31 +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 {
QInstaller::openForRead(&archiveFile, archiveFile.fileName());
2011-02-21 16:30:31 +01:00
const QByteArray archiveData = archiveFile.readAll();
archiveFile.close();
QInstaller::openForWrite(&archiveHashFile, archiveHashFile.fileName());
2011-02-21 16:30:31 +01:00
const QByteArray hashOfArchiveData = QCryptographicHash::hash(archiveData,
QCryptographicHash::Sha1).toHex();
archiveHashFile.write(hashOfArchiveData);
qDebug() << "Generated sha1 hash:" << hashOfArchiveData;
infos[i].copiedArchives.append(archiveHashFile.fileName());
2011-02-21 16:30:31 +01:00
archiveHashFile.close();
} catch (const QInstaller::Error &/*e*/) {
2011-02-21 16:30:31 +01:00
archiveFile.close();
archiveHashFile.close();
2011-02-21 16:30:31 +01:00
throw;
}
}
}
}