2011-02-21 16:30:31 +01:00
|
|
|
/**************************************************************************
|
|
|
|
**
|
2015-02-17 11:18:57 +01:00
|
|
|
** Copyright (C) 2015 The Qt Company Ltd.
|
|
|
|
** Contact: http://www.qt.io/licensing/
|
2011-02-21 16:30:31 +01:00
|
|
|
**
|
2012-12-21 10:31:17 +01:00
|
|
|
** This file is part of the Qt Installer Framework.
|
2011-02-21 16:30:31 +01:00
|
|
|
**
|
2012-12-21 10:31:17 +01:00
|
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
|
|
|
** Commercial License Usage
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
2015-02-17 11:18:57 +01:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
|
|
** and conditions see http://qt.io/terms-conditions. For further
|
|
|
|
** information use the contact form at http://www.qt.io/contact-us.
|
2011-02-21 16:30:31 +01:00
|
|
|
**
|
|
|
|
** GNU Lesser General Public License Usage
|
2012-12-21 10:31:17 +01:00
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
2014-10-16 11:51:47 +02:00
|
|
|
** General Public License version 2.1 or version 3 as published by the Free
|
|
|
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
|
|
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
|
|
|
** following information to ensure the GNU Lesser General Public License
|
|
|
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
|
|
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
2012-12-21 10:31:17 +01:00
|
|
|
**
|
2015-02-17 11:18:57 +01:00
|
|
|
** As a special exception, The Qt Company gives you certain additional
|
|
|
|
** rights. These rights are described in The Qt Company LGPL Exception
|
2012-02-06 09:23:20 +01:00
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
**
|
|
|
|
**
|
2012-12-21 10:31:17 +01:00
|
|
|
** $QT_END_LICENSE$
|
2011-02-21 16:30:31 +01:00
|
|
|
**
|
|
|
|
**************************************************************************/
|
2012-03-13 16:38:56 +01:00
|
|
|
#include "repositorygen.h"
|
|
|
|
|
2014-06-23 13:15:15 +02:00
|
|
|
#include <fileio.h>
|
2012-03-13 16:38:56 +01:00
|
|
|
#include <fileutils.h>
|
|
|
|
#include <errors.h>
|
2013-02-28 17:30:06 +01:00
|
|
|
#include <globals.h>
|
2015-06-09 16:05:27 +02:00
|
|
|
#include <lib7z_create.h>
|
2012-02-28 15:01:08 +01:00
|
|
|
#include <lib7z_facade.h>
|
2015-06-09 16:05:27 +02:00
|
|
|
#include <lib7z_list.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>
|
2013-05-08 13:26:41 +02:00
|
|
|
#include <scriptengine.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-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
|
|
|
{
|
|
|
|
std::cout << " -p|--packages dir The directory containing the available packages." << std::endl;
|
2013-06-11 15:16:49 +02:00
|
|
|
std::cout << " This entry can be given multiple times." << std::endl;
|
2012-03-07 16:47:08 +01:00
|
|
|
|
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;
|
|
|
|
|
2013-06-17 14:01:21 +02:00
|
|
|
std::cout << " --ignore-translations Do not use any translation" << std::endl;
|
2012-03-07 16:47:47 +01:00
|
|
|
std::cout << " --ignore-invalid-packages Ignore all invalid packages instead of aborting." << std::endl;
|
2012-03-07 16:47:08 +01:00
|
|
|
}
|
|
|
|
|
2013-03-25 13:36:54 +01:00
|
|
|
QString QInstallerTools::makePathAbsolute(const QString &path)
|
|
|
|
{
|
|
|
|
if (QFileInfo(path).isRelative())
|
|
|
|
return QDir::current().absoluteFilePath(path);
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
2013-03-13 14:56:36 +01:00
|
|
|
void QInstallerTools::copyWithException(const QString &source, const QString &target, const QString &kind)
|
|
|
|
{
|
2015-07-08 16:56:22 +02:00
|
|
|
qDebug() << "Copying associated" << kind << "file" << source;
|
2013-03-13 14:56:36 +01:00
|
|
|
|
|
|
|
const QFileInfo targetFileInfo(target);
|
2013-03-22 15:01:32 +01:00
|
|
|
if (!targetFileInfo.dir().exists())
|
2013-03-13 14:56:36 +01:00
|
|
|
QInstaller::mkpath(targetFileInfo.absolutePath());
|
|
|
|
|
2013-03-22 15:01:32 +01:00
|
|
|
QFile sourceFile(source);
|
2013-03-13 14:56:36 +01:00
|
|
|
if (!sourceFile.copy(target)) {
|
|
|
|
qDebug() << "failed!\n";
|
2015-06-24 10:15:16 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Cannot copy the %1 file from \"%2\" to \"%3\": "
|
|
|
|
"%4").arg(kind, QDir::toNativeSeparators(source), QDir::toNativeSeparators(target),
|
2013-03-22 15:01:32 +01:00
|
|
|
/* in case of an existing target the error String does not show the file */
|
|
|
|
(targetFileInfo.exists() ? QLatin1String("Target already exist.") : sourceFile.errorString())));
|
2013-03-13 14:56:36 +01:00
|
|
|
}
|
2013-03-22 15:01:32 +01:00
|
|
|
|
2013-03-13 14:56:36 +01:00
|
|
|
qDebug() << "done.\n";
|
|
|
|
}
|
|
|
|
|
2013-03-25 14:18:18 +01:00
|
|
|
static QStringList copyFilesFromNode(const QString &parentNode, const QString &childNode, const QString &attr,
|
|
|
|
const QString &kind, const QDomNode &package, const PackageInfo &info, const QString &targetDir)
|
|
|
|
{
|
|
|
|
QStringList copiedFiles;
|
|
|
|
const QDomNodeList nodes = package.firstChildElement(parentNode).childNodes();
|
|
|
|
for (int i = 0; i < nodes.count(); ++i) {
|
|
|
|
const QDomNode node = nodes.at(i);
|
|
|
|
if (node.nodeName() != childNode)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
const QDir dir(QString::fromLatin1("%1/meta").arg(info.directory));
|
|
|
|
const QString filter = attr.isEmpty() ? node.toElement().text() : node.toElement().attribute(attr);
|
|
|
|
const QStringList files = dir.entryList(QStringList(filter), QDir::Files);
|
|
|
|
if (files.isEmpty()) {
|
2015-06-24 10:15:16 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Cannot find any %1 matching \"%2\" "
|
|
|
|
"while copying %1 of \"%3\".").arg(kind, filter, info.name));
|
2013-03-25 14:18:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
foreach (const QString &file, files) {
|
|
|
|
const QString source(QString::fromLatin1("%1/meta/%2").arg(info.directory, file));
|
|
|
|
const QString target(QString::fromLatin1("%1/%2/%3").arg(targetDir, info.name, file));
|
|
|
|
copyWithException(source, target, kind);
|
|
|
|
copiedFiles.append(file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return copiedFiles;
|
|
|
|
}
|
|
|
|
|
2013-03-25 09:50:05 +01:00
|
|
|
void QInstallerTools::copyMetaData(const QString &_targetDir, const QString &metaDataDir,
|
2013-06-06 09:49:46 +02:00
|
|
|
const PackageInfoVector &packages, const QString &appName, const QString &appVersion)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2013-03-25 14:18:18 +01:00
|
|
|
const QString targetDir = makePathAbsolute(_targetDir);
|
|
|
|
if (!QFile::exists(targetDir))
|
|
|
|
QInstaller::mkpath(targetDir);
|
2011-02-21 16:30:31 +01:00
|
|
|
|
|
|
|
QDomDocument doc;
|
|
|
|
QDomElement root;
|
2013-03-25 09:50:05 +01:00
|
|
|
QFile existingUpdatesXml(QFileInfo(metaDataDir, QLatin1String("Updates.xml")).absoluteFilePath());
|
2013-03-25 14:18:18 +01:00
|
|
|
if (existingUpdatesXml.open(QIODevice::ReadOnly) && doc.setContent(&existingUpdatesXml)) {
|
|
|
|
root = doc.documentElement();
|
|
|
|
// remove entry for this component from existing Updates.xml, if found
|
|
|
|
foreach (const PackageInfo &info, packages) {
|
|
|
|
const QDomNodeList packageNodes = root.childNodes();
|
|
|
|
for (int i = packageNodes.count() - 1; i >= 0; --i) {
|
|
|
|
const QDomNode node = packageNodes.at(i);
|
|
|
|
if (node.nodeName() != QLatin1String("PackageUpdate"))
|
|
|
|
continue;
|
|
|
|
if (node.firstChildElement(QLatin1String("Name")).text() != info.name)
|
|
|
|
continue;
|
|
|
|
root.removeChild(node);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
existingUpdatesXml.close();
|
|
|
|
} else {
|
2012-03-15 14:53:47 +01:00
|
|
|
root = doc.createElement(QLatin1String("Updates"));
|
2013-03-25 09:50:05 +01:00
|
|
|
root.appendChild(doc.createElement(QLatin1String("ApplicationName"))).appendChild(doc
|
|
|
|
.createTextNode(appName));
|
|
|
|
root.appendChild(doc.createElement(QLatin1String("ApplicationVersion"))).appendChild(doc
|
|
|
|
.createTextNode(appVersion));
|
|
|
|
root.appendChild(doc.createElement(QLatin1String("Checksum"))).appendChild(doc
|
|
|
|
.createTextNode(QLatin1String("true")));
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
2013-03-25 14:18:18 +01:00
|
|
|
foreach (const PackageInfo &info, packages) {
|
|
|
|
if (!QDir(targetDir).mkpath(info.name))
|
2015-06-24 10:15:16 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Cannot create directory \"%1\".").arg(info.name));
|
2013-03-25 14:18:18 +01:00
|
|
|
|
|
|
|
const QString packageXmlPath = QString::fromLatin1("%1/meta/package.xml").arg(info.directory);
|
2015-07-08 16:56:22 +02:00
|
|
|
qDebug() << "Copy meta data for package" << info.name << "using" << packageXmlPath;
|
2011-02-21 16:30:31 +01:00
|
|
|
|
|
|
|
QFile file(packageXmlPath);
|
2014-06-23 13:15:15 +02:00
|
|
|
QInstaller::openForRead(&file);
|
2013-03-25 14:18:18 +01:00
|
|
|
|
2011-02-21 16:30:31 +01:00
|
|
|
QString errMsg;
|
|
|
|
int line = 0;
|
2013-03-25 14:18:18 +01:00
|
|
|
int column = 0;
|
|
|
|
QDomDocument packageXml;
|
|
|
|
if (!packageXml.setContent(&file, &errMsg, &line, &column)) {
|
2015-06-24 10:15:16 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Cannot parse \"%1\": line: %2, column: %3: %4 (%5)")
|
|
|
|
.arg(QDir::toNativeSeparators(packageXmlPath)).arg(line).arg(column).arg(errMsg, info.name));
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
2012-03-15 14:53:47 +01:00
|
|
|
QDomElement update = doc.createElement(QLatin1String("PackageUpdate"));
|
2013-03-25 14:18:18 +01:00
|
|
|
QDomNode nameElement = update.appendChild(doc.createElement(QLatin1String("Name")));
|
|
|
|
nameElement.appendChild(doc.createTextNode(info.name));
|
2012-09-27 15:50:36 +02:00
|
|
|
|
|
|
|
// 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
|
|
|
|
2013-02-19 20:18:01 +01:00
|
|
|
bool foundDefault = false;
|
|
|
|
bool foundVirtual = false;
|
2013-03-08 11:22:02 +01:00
|
|
|
bool foundDisplayName = false;
|
2013-08-01 15:56:52 +02:00
|
|
|
bool foundDownloadableArchives = false;
|
2013-03-25 14:18:18 +01:00
|
|
|
const QDomNode package = packageXml.firstChildElement(QLatin1String("Package"));
|
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();
|
2013-02-19 20:18:01 +01:00
|
|
|
|
|
|
|
if (key == QLatin1String("Default"))
|
|
|
|
foundDefault = true;
|
|
|
|
if (key == QLatin1String("Virtual"))
|
|
|
|
foundVirtual = true;
|
2013-03-08 11:22:02 +01:00
|
|
|
if (key == QLatin1String("DisplayName"))
|
|
|
|
foundDisplayName = true;
|
2013-08-01 15:56:52 +02:00
|
|
|
if (key == QLatin1String("DownloadableArchives"))
|
|
|
|
foundDownloadableArchives = true;
|
2012-09-27 15:50:36 +02:00
|
|
|
if (node.isComment() || blackList.contains(key))
|
2013-02-19 20:18:01 +01:00
|
|
|
continue; // just skip comments and some tags...
|
|
|
|
|
2011-10-13 13:28:59 +02:00
|
|
|
QDomElement element = doc.createElement(key);
|
2013-03-25 14:18:18 +01:00
|
|
|
for (int j = 0; j < node.attributes().size(); ++j) {
|
|
|
|
element.setAttribute(node.attributes().item(j).toAttr().name(),
|
|
|
|
node.attributes().item(j).toAttr().value());
|
2011-10-13 13:28:59 +02:00
|
|
|
}
|
2013-03-25 14:18:18 +01:00
|
|
|
update.appendChild(element).appendChild(doc.createTextNode(node.toElement().text()));
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
2013-02-19 20:18:01 +01:00
|
|
|
if (foundDefault && foundVirtual) {
|
|
|
|
throw QInstaller::Error(QString::fromLatin1("Error: <Default> and <Virtual> elements are "
|
2015-06-24 10:15:16 +02:00
|
|
|
"mutually exclusive in file \"%1\".").arg(QDir::toNativeSeparators(packageXmlPath)));
|
2013-02-19 20:18:01 +01:00
|
|
|
}
|
|
|
|
|
2013-03-08 11:22:02 +01:00
|
|
|
if (!foundDisplayName) {
|
2015-07-08 16:56:22 +02:00
|
|
|
qWarning() << "No DisplayName tag found at" << info.name << ", using component Name instead.";
|
2013-03-08 11:22:02 +01:00
|
|
|
QDomElement displayNameElement = doc.createElement(QLatin1String("DisplayName"));
|
2013-03-25 14:18:18 +01:00
|
|
|
update.appendChild(displayNameElement).appendChild(doc.createTextNode(info.name));
|
2013-03-08 11:22:02 +01:00
|
|
|
}
|
|
|
|
|
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;
|
2013-03-25 14:18:18 +01:00
|
|
|
const QDir dataDir = QString::fromLatin1("%1/%2/data").arg(metaDataDir, info.name);
|
|
|
|
const QFileInfoList entries = dataDir.exists() ? dataDir.entryInfoList(filters | QDir::Dirs)
|
|
|
|
: QDir(QString::fromLatin1("%1/%2").arg(metaDataDir, info.name)).entryInfoList(filters);
|
2015-07-08 16:56:22 +02:00
|
|
|
qDebug() << "calculate size of directory" << dataDir.absolutePath();
|
2011-11-17 22:44:56 +01:00
|
|
|
foreach (const QFileInfo &fi, entries) {
|
2011-02-21 16:30:31 +01:00
|
|
|
try {
|
|
|
|
if (fi.isDir()) {
|
|
|
|
QDirIterator recursDirIt(fi.filePath(), QDirIterator::Subdirectories);
|
|
|
|
while (recursDirIt.hasNext()) {
|
2013-05-29 14:28:27 +02:00
|
|
|
recursDirIt.next();
|
|
|
|
const quint64 size = QInstaller::fileSize(recursDirIt.fileInfo());
|
2012-11-07 14:07:05 +01:00
|
|
|
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();
|
2014-06-23 13:15:15 +02:00
|
|
|
QInstaller::openForRead(&archive);
|
2013-03-25 14:18:18 +01:00
|
|
|
|
|
|
|
QVector<Lib7z::File>::const_iterator fileIt;
|
|
|
|
const QVector<Lib7z::File> files = Lib7z::listArchive(&archive);
|
|
|
|
for (fileIt = files.begin(); fileIt != files.end(); ++fileIt)
|
|
|
|
componentSize += fileIt->uncompressedSize;
|
2011-02-21 16:30:31 +01:00
|
|
|
} else {
|
2012-02-15 13:39:53 +01:00
|
|
|
// otherwise just add its size
|
2013-05-29 14:28:27 +02:00
|
|
|
const quint64 size = QInstaller::fileSize(fi);
|
2012-11-07 14:07:05 +01:00
|
|
|
componentSize += size;
|
|
|
|
compressedComponentSize += size;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
2013-03-25 14:18:18 +01:00
|
|
|
} catch (const QInstaller::Error &error) {
|
2015-07-08 16:56:22 +02:00
|
|
|
qDebug().noquote() << error.message();
|
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);
|
2013-04-09 13:47:44 +02:00
|
|
|
// adding the OS attribute to be compatible with old sdks
|
|
|
|
fileElement.setAttribute(QLatin1String("OS"), QLatin1String("Any"));
|
2012-09-27 15:51:34 +02:00
|
|
|
update.appendChild(fileElement);
|
2011-02-21 16:30:31 +01:00
|
|
|
|
|
|
|
root.appendChild(update);
|
|
|
|
|
2013-03-25 14:18:18 +01:00
|
|
|
// copy script file
|
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()) {
|
2013-03-25 14:18:18 +01:00
|
|
|
QFile scriptFile(QString::fromLatin1("%1/meta/%2").arg(info.directory, script));
|
2014-04-03 15:02:00 +02:00
|
|
|
if (!scriptFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
2015-06-24 10:15:16 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Cannot open component script at \"%1\".")
|
|
|
|
.arg(QDir::toNativeSeparators(scriptFile.fileName())));
|
2011-11-08 14:36:12 +01:00
|
|
|
}
|
2013-08-01 15:56:52 +02:00
|
|
|
|
2014-04-10 11:07:09 +02:00
|
|
|
const QString scriptContent = QLatin1String("(function() {")
|
|
|
|
+ QString::fromUtf8(scriptFile.readAll())
|
|
|
|
+ QLatin1String(";"
|
2014-04-03 15:02:00 +02:00
|
|
|
" if (typeof Component == \"undefined\")"
|
|
|
|
" throw \"Missing Component constructor. Please check your script.\";"
|
2014-04-10 11:07:09 +02:00
|
|
|
"})();");
|
2014-04-03 15:02:00 +02:00
|
|
|
|
2013-08-01 15:56:52 +02:00
|
|
|
// if the user isn't aware of the downloadable archives value we will add it automatically later
|
|
|
|
foundDownloadableArchives |= scriptContent.contains(QLatin1String("addDownloadableArchive"))
|
|
|
|
|| scriptContent.contains(QLatin1String("removeDownloadableArchive"));
|
|
|
|
|
2014-06-02 15:14:12 +02:00
|
|
|
static QInstaller::ScriptEngine testScriptEngine;
|
|
|
|
const QJSValue value = testScriptEngine.evaluate(scriptContent, scriptFile.fileName());
|
|
|
|
if (value.isError()) {
|
2014-04-03 15:02:00 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Exception while loading component "
|
2015-06-24 10:15:16 +02:00
|
|
|
"script at \"%1\": %2").arg(QDir::toNativeSeparators(scriptFile.fileName()),
|
|
|
|
value.toString().isEmpty() ?
|
|
|
|
QString::fromLatin1("Unknown error.") : value.toString()));
|
2012-03-27 13:55:25 +02:00
|
|
|
}
|
2011-11-08 14:36:12 +01:00
|
|
|
|
2013-03-25 14:18:18 +01:00
|
|
|
const QString toLocation(QString::fromLatin1("%1/%2/%3").arg(targetDir, info.name, script));
|
2014-11-17 14:40:57 +01:00
|
|
|
copyWithException(scriptFile.fileName(), toLocation, QInstaller::scScript);
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
2013-08-01 15:56:52 +02:00
|
|
|
// write DownloadableArchives tag if that is missed by the user
|
|
|
|
if (!foundDownloadableArchives && !info.copiedFiles.isEmpty()) {
|
|
|
|
QStringList realContentFiles;
|
|
|
|
foreach (const QString &filePath, info.copiedFiles) {
|
|
|
|
if (!filePath.endsWith(QLatin1String(".sha1"), Qt::CaseInsensitive)) {
|
|
|
|
const QString fileName = QFileInfo(filePath).fileName();
|
|
|
|
// remove unnecessary version string from filename and add it to the list
|
|
|
|
realContentFiles.append(fileName.mid(info.version.count()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
update.appendChild(doc.createElement(QLatin1String("DownloadableArchives"))).appendChild(doc
|
|
|
|
.createTextNode(realContentFiles.join(QChar::fromLatin1(','))));
|
|
|
|
}
|
|
|
|
|
2011-02-21 16:30:31 +01:00
|
|
|
// copy user interfaces
|
2013-03-25 14:18:18 +01:00
|
|
|
const QStringList uiFiles = copyFilesFromNode(QLatin1String("UserInterfaces"),
|
|
|
|
QLatin1String("UserInterface"), QString(), QLatin1String("user interface"), package, info,
|
|
|
|
targetDir);
|
|
|
|
if (!uiFiles.isEmpty()) {
|
|
|
|
update.appendChild(doc.createElement(QLatin1String("UserInterfaces"))).appendChild(doc
|
|
|
|
.createTextNode(uiFiles.join(QChar::fromLatin1(','))));
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// copy translations
|
2013-03-25 14:18:18 +01:00
|
|
|
QStringList trFiles;
|
2012-03-07 16:47:47 +01:00
|
|
|
if (!qApp->arguments().contains(QString::fromLatin1("--ignore-translations"))) {
|
2013-03-25 14:18:18 +01:00
|
|
|
trFiles = copyFilesFromNode(QLatin1String("Translations"), QLatin1String("Translation"),
|
|
|
|
QString(), QLatin1String("translation"), package, info, targetDir);
|
|
|
|
if (!trFiles.isEmpty()) {
|
|
|
|
update.appendChild(doc.createElement(QLatin1String("Translations"))).appendChild(doc
|
|
|
|
.createTextNode(trFiles.join(QChar::fromLatin1(','))));
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// copy license files
|
2013-03-25 14:18:18 +01:00
|
|
|
const QStringList licenses = copyFilesFromNode(QLatin1String("Licenses"), QLatin1String("License"),
|
|
|
|
QLatin1String("file"), QLatin1String("license"), package, info, targetDir);
|
|
|
|
if (!licenses.isEmpty()) {
|
|
|
|
foreach (const QString &trFile, trFiles) {
|
|
|
|
// Copy translated license file based on the assumption that it will have the same base name
|
|
|
|
// as the original license plus the file name of an existing translation file without suffix.
|
|
|
|
foreach (const QString &license, licenses) {
|
|
|
|
const QFileInfo untranslated(license);
|
|
|
|
const QString translatedLicense = QString::fromLatin1("%2_%3.%4").arg(untranslated
|
|
|
|
.baseName(), QFileInfo(trFile).baseName(), untranslated.completeSuffix());
|
|
|
|
// ignore copy failure, that's just about the translations
|
|
|
|
QFile::copy(QString::fromLatin1("%1/meta/%2").arg(info.directory).arg(translatedLicense),
|
|
|
|
QString::fromLatin1("%1/%2/%3").arg(targetDir, info.name, translatedLicense));
|
2012-02-15 15:26:45 +01:00
|
|
|
}
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
2012-03-15 14:53:47 +01:00
|
|
|
update.appendChild(package.firstChildElement(QLatin1String("Licenses")).cloneNode());
|
2013-03-25 14:18:18 +01:00
|
|
|
}
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
doc.appendChild(root);
|
|
|
|
|
2013-03-25 14:18:18 +01:00
|
|
|
QFile targetUpdatesXml(targetDir + QLatin1String("/Updates.xml"));
|
2014-06-23 13:15:15 +02:00
|
|
|
QInstaller::openForWrite(&targetUpdatesXml);
|
2013-03-25 14:18:18 +01:00
|
|
|
QInstaller::blockingWrite(&targetUpdatesXml, doc.toByteArray());
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
2013-06-11 15:16:49 +02:00
|
|
|
PackageInfoVector QInstallerTools::createListOfPackages(const QStringList &packagesDirectories,
|
2013-06-20 10:58:53 +02:00
|
|
|
QStringList *packagesToFilter, FilterType filterType)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2013-03-13 14:56:36 +01:00
|
|
|
qDebug() << "\nCollecting information about available packages...";
|
2012-03-12 19:02:53 +01:00
|
|
|
|
|
|
|
bool ignoreInvalidPackages = qApp->arguments().contains(QString::fromLatin1("--ignore-invalid-packages"));
|
|
|
|
|
|
|
|
PackageInfoVector dict;
|
2013-06-11 15:16:49 +02:00
|
|
|
QFileInfoList entries;
|
|
|
|
foreach (const QString &packagesDirectory, packagesDirectories)
|
|
|
|
entries.append(QDir(packagesDirectory).entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot));
|
2015-04-01 13:41:21 +02:00
|
|
|
for (QFileInfoList::const_iterator it = entries.constBegin(); it != entries.constEnd(); ++it) {
|
2012-03-12 19:02:53 +01:00
|
|
|
if (filterType == Exclude) {
|
2013-06-20 10:58:53 +02:00
|
|
|
// Check for current file in exclude list, if found, skip it and remove it from exclude list
|
|
|
|
if (packagesToFilter->contains(it->fileName())) {
|
|
|
|
packagesToFilter->removeAll(it->fileName());
|
2012-03-12 19:02:53 +01:00
|
|
|
continue;
|
2013-06-20 10:58:53 +02:00
|
|
|
}
|
2012-03-12 19:02:53 +01:00
|
|
|
} else {
|
2013-06-20 10:58:53 +02:00
|
|
|
// Check for current file in include list, if not found, skip it; if found, remove it from include list
|
|
|
|
if (!packagesToFilter->contains(it->fileName()))
|
2012-03-12 19:02:53 +01:00
|
|
|
continue;
|
2013-06-20 10:58:53 +02:00
|
|
|
packagesToFilter->removeAll(it->fileName());
|
2012-03-12 19:02:53 +01:00
|
|
|
}
|
2015-07-08 16:56:22 +02:00
|
|
|
qDebug() << "Found subdirectory" << 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;
|
2015-06-24 10:15:16 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Component \"%1\" must not contain '-'. This is not "
|
2013-03-25 13:44:16 +01:00
|
|
|
"allowed, because dashes are used as the separator between the component name and the "
|
2015-06-24 10:15:16 +02:00
|
|
|
"version number internally.").arg(QDir::toNativeSeparators(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;
|
2015-06-24 10:15:16 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Component \"%1\" does not contain a package "
|
|
|
|
"description (meta/package.xml is missing).").arg(QDir::toNativeSeparators(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;
|
2015-06-24 10:15:16 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Component package description in \"%1\" is invalid. "
|
|
|
|
"Error at line: %2, column: %3 -> %4").arg(QDir::toNativeSeparators(fileInfo.absoluteFilePath()),
|
|
|
|
QString::number(errorLine),
|
|
|
|
QString::number(errorColumn), error));
|
2012-01-16 23:42:54 +01:00
|
|
|
}
|
2012-03-12 19:02:53 +01:00
|
|
|
|
2013-02-01 13:34:13 +01:00
|
|
|
const QDomElement packageElement = doc.firstChildElement(QLatin1String("Package"));
|
|
|
|
const QString name = packageElement.firstChildElement(QLatin1String("Name")).text();
|
2012-09-27 15:50:36 +02:00
|
|
|
if (!name.isEmpty() && name != it->fileName()) {
|
2015-07-08 16:56:22 +02:00
|
|
|
qWarning().nospace() << "The <Name> tag in the file " << fileInfo.absoluteFilePath()
|
|
|
|
<< " is ignored - the installer uses the path element right before the 'meta'"
|
|
|
|
<< " (" << it->fileName() << ")";
|
2012-03-12 19:02:53 +01:00
|
|
|
}
|
|
|
|
|
2014-02-11 12:02:26 +01:00
|
|
|
QString releaseDate = packageElement.firstChildElement(QLatin1String("ReleaseDate")).text();
|
|
|
|
if (releaseDate.isEmpty()) {
|
2015-06-24 10:15:16 +02:00
|
|
|
qWarning("Release date for \"%s\" is empty! Using the current date instead.",
|
2014-02-11 12:02:26 +01:00
|
|
|
qPrintable(fileInfo.absoluteFilePath()));
|
|
|
|
releaseDate = QDate::currentDate().toString(Qt::ISODate);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!QDate::fromString(releaseDate, Qt::ISODate).isValid()) {
|
2013-02-01 13:34:13 +01:00
|
|
|
if (ignoreInvalidPackages)
|
|
|
|
continue;
|
2015-06-24 10:15:16 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Release date for \"%1\" is invalid! <ReleaseDate>%2"
|
|
|
|
"</ReleaseDate>. Supported format: YYYY-MM-DD").arg(QDir::toNativeSeparators(fileInfo.absoluteFilePath()),
|
|
|
|
releaseDate));
|
2013-02-01 13:34:13 +01:00
|
|
|
}
|
|
|
|
|
2012-03-12 19:02:53 +01:00
|
|
|
PackageInfo info;
|
2012-09-27 15:50:36 +02:00
|
|
|
info.name = it->fileName();
|
2013-02-01 13:34:13 +01:00
|
|
|
info.version = packageElement.firstChildElement(QLatin1String("Version")).text();
|
2012-03-12 19:02:53 +01:00
|
|
|
if (!QRegExp(QLatin1String("[0-9]+((\\.|-)[0-9]+)*")).exactMatch(info.version)) {
|
|
|
|
if (ignoreInvalidPackages)
|
|
|
|
continue;
|
2015-06-24 10:15:16 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Component version for \"%1\" is invalid! <Version>%2</Version>")
|
|
|
|
.arg(QDir::toNativeSeparators(fileInfo.absoluteFilePath()), info.version));
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
2013-02-01 13:34:13 +01:00
|
|
|
info.dependencies = packageElement.firstChildElement(QLatin1String("Dependencies")).text()
|
2013-02-28 17:30:06 +01:00
|
|
|
.split(QInstaller::commaRegExp(), QString::SkipEmptyParts);
|
2012-03-12 19:02:53 +01:00
|
|
|
info.directory = it->filePath();
|
|
|
|
dict.push_back(info);
|
|
|
|
|
2015-07-08 16:56:22 +02:00
|
|
|
qDebug() << "- it provides the package" << info.name << " - " << info.version;
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
|
|
|
|
2013-08-01 14:46:00 +02:00
|
|
|
if (!packagesToFilter->isEmpty() && packagesToFilter->at(0) != QString::fromLatin1(
|
|
|
|
"X_fake_filter_component_for_online_only_installer_X")) {
|
2013-06-20 10:58:53 +02:00
|
|
|
qWarning() << "The following explicitly given packages could not be found\n in package directory:" << *packagesToFilter;
|
|
|
|
}
|
|
|
|
|
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)) {
|
2015-06-24 10:15:16 +02:00
|
|
|
qDebug() << "Cannot 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;
|
2015-06-09 16:04:24 +02:00
|
|
|
Lib7z::createArchive(tmpTarget, QStringList() << absPath, Lib7z::QTmpFile::No);
|
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;
|
2013-03-25 13:44:16 +01:00
|
|
|
if (!tmp.rename(finalTarget)) {
|
2015-06-24 10:15:16 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Cannot move file \"%1\" to \"%2\".").arg(
|
|
|
|
QDir::toNativeSeparators(tmpTarget), QDir::toNativeSeparators(finalTarget)));
|
2013-03-25 13:44:16 +01:00
|
|
|
}
|
2011-02-21 16:30:31 +01:00
|
|
|
}
|
2012-02-28 16:11:44 +01:00
|
|
|
|
2014-06-23 13:15:15 +02:00
|
|
|
QInstaller::openForWrite(&existingUpdatesXml);
|
2012-03-13 17:53:03 +01:00
|
|
|
QInstaller::blockingWrite(&existingUpdatesXml, doc.toByteArray());
|
2011-02-21 16:30:31 +01:00
|
|
|
existingUpdatesXml.close();
|
|
|
|
}
|
|
|
|
|
2013-06-11 15:16:49 +02:00
|
|
|
void QInstallerTools::copyComponentData(const QStringList &packageDirs, const QString &repoDir,
|
2013-03-25 09:50:05 +01:00
|
|
|
PackageInfoVector *const infos)
|
2011-02-21 16:30:31 +01:00
|
|
|
{
|
2013-03-25 09:50:05 +01:00
|
|
|
for (int i = 0; i < infos->count(); ++i) {
|
|
|
|
const PackageInfo info = infos->at(i);
|
2012-02-28 17:50:35 +01:00
|
|
|
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)) {
|
2015-06-24 10:15:16 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Cannot create repository directory 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;
|
2013-06-11 15:16:49 +02:00
|
|
|
foreach (const QString &packageDir, packageDirs) {
|
|
|
|
const QDir dataDir(QString::fromLatin1("%1/%2/data").arg(packageDir, name));
|
|
|
|
foreach (const QString &entry, dataDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::Files)) {
|
|
|
|
QFileInfo fileInfo(dataDir.absoluteFilePath(entry));
|
|
|
|
if (fileInfo.isFile() && !fileInfo.isSymLink()) {
|
|
|
|
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);
|
2015-07-08 16:56:22 +02:00
|
|
|
qDebug() << "Copying archive from" << tmp.fileName() << "to" << target;
|
2013-06-11 15:16:49 +02:00
|
|
|
if (!tmp.copy(target)) {
|
2015-06-24 10:15:16 +02:00
|
|
|
throw QInstaller::Error(QString::fromLatin1("Cannot copy file \"%1\" to \"%2\": %3")
|
|
|
|
.arg(QDir::toNativeSeparators(tmp.fileName()), QDir::toNativeSeparators(target), tmp.errorString()));
|
2013-06-11 15:16:49 +02:00
|
|
|
}
|
|
|
|
compressedFiles.append(target);
|
|
|
|
} else {
|
|
|
|
filesToCompress.append(absoluteEntryFilePath);
|
2012-08-21 12:10:07 +02:00
|
|
|
}
|
2013-06-11 15:16:49 +02:00
|
|
|
} else if (fileInfo.isDir()) {
|
|
|
|
qDebug() << "Compressing data directory" << entry;
|
|
|
|
QString target = QString::fromLatin1("%1/%3%2.7z").arg(namedRepoDir, entry, info.version);
|
2015-06-09 16:04:24 +02:00
|
|
|
Lib7z::createArchive(target, QStringList() << dataDir.absoluteFilePath(entry),
|
|
|
|
Lib7z::QTmpFile::No);
|
2012-08-21 12:10:07 +02:00
|
|
|
compressedFiles.append(target);
|
2013-06-11 15:16:49 +02:00
|
|
|
} else if (fileInfo.isSymLink()) {
|
|
|
|
filesToCompress.append(dataDir.absoluteFilePath(entry));
|
2012-02-28 17:50:35 +01:00
|
|
|
}
|
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);
|
2015-06-09 16:04:24 +02:00
|
|
|
Lib7z::createArchive(target, filesToCompress, Lib7z::QTmpFile::No);
|
2012-08-21 12:10:07 +02:00
|
|
|
compressedFiles.append(target);
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach (const QString &target, compressedFiles) {
|
2013-07-29 14:09:48 +02:00
|
|
|
(*infos)[i].copiedFiles.append(target);
|
2012-02-28 17:50:35 +01:00
|
|
|
|
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 {
|
2014-06-23 13:15:15 +02:00
|
|
|
QInstaller::openForRead(&archiveFile);
|
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
|
|
|
|
2014-06-23 13:15:15 +02:00
|
|
|
QInstaller::openForWrite(&archiveHashFile);
|
2011-02-21 16:30:31 +01:00
|
|
|
archiveHashFile.write(hashOfArchiveData);
|
2012-02-28 17:50:35 +01:00
|
|
|
qDebug() << "Generated sha1 hash:" << hashOfArchiveData;
|
2013-07-29 14:09:48 +02:00
|
|
|
(*infos)[i].copiedFiles.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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|