From ac2319b4f0e67da02880bdf1f8832cf3f527c252 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Tue, 9 Apr 2013 10:21:54 +0200 Subject: create getrepositorycontent tool It is a very useful tool to get repositories locally for testing. Change-Id: Ia83841c3e5c96ab369c35580dd98141cf22ed643 Reviewed-by: Karsten Heimrich --- .../domnodedebugstreamoperator.cpp | 53 +++ .../domnodedebugstreamoperator.h | 51 +++ tools/getrepositorycontent/downloader.cpp | 114 ++++++ tools/getrepositorycontent/downloader.h | 76 ++++ .../getrepositorycontent/getrepositorycontent.pro | 22 + tools/getrepositorycontent/main.cpp | 450 +++++++++++++++++++++ tools/getrepositorycontent/textprogressbar.cpp | 98 +++++ tools/getrepositorycontent/textprogressbar.h | 63 +++ 8 files changed, 927 insertions(+) create mode 100644 tools/getrepositorycontent/domnodedebugstreamoperator.cpp create mode 100644 tools/getrepositorycontent/domnodedebugstreamoperator.h create mode 100644 tools/getrepositorycontent/downloader.cpp create mode 100644 tools/getrepositorycontent/downloader.h create mode 100644 tools/getrepositorycontent/getrepositorycontent.pro create mode 100644 tools/getrepositorycontent/main.cpp create mode 100644 tools/getrepositorycontent/textprogressbar.cpp create mode 100644 tools/getrepositorycontent/textprogressbar.h (limited to 'tools/getrepositorycontent') diff --git a/tools/getrepositorycontent/domnodedebugstreamoperator.cpp b/tools/getrepositorycontent/domnodedebugstreamoperator.cpp new file mode 100644 index 000000000..511b4a224 --- /dev/null +++ b/tools/getrepositorycontent/domnodedebugstreamoperator.cpp @@ -0,0 +1,53 @@ +/************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Installer Framework. +** +** $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 +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#include "domnodedebugstreamoperator.h" + +QDebug operator<<(QDebug dbg, const QDomNode &domNode) +{ + if (domNode.isNull()) + return dbg << "domNode is Null"; + QString debugOutput; + QTextStream stream(&debugOutput); + domNode.save(stream, 4); + + return dbg << debugOutput; +} diff --git a/tools/getrepositorycontent/domnodedebugstreamoperator.h b/tools/getrepositorycontent/domnodedebugstreamoperator.h new file mode 100644 index 000000000..f48918f77 --- /dev/null +++ b/tools/getrepositorycontent/domnodedebugstreamoperator.h @@ -0,0 +1,51 @@ +/************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Installer Framework. +** +** $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 +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#ifndef DEBUGDOMNODE_H +#define DEBUGDOMNODE_H + +#include +#include + +QDebug operator<<(QDebug dbg, const QDomNode &domNode); + + +#endif // DEBUGDOMNODE_H diff --git a/tools/getrepositorycontent/downloader.cpp b/tools/getrepositorycontent/downloader.cpp new file mode 100644 index 000000000..0eb19139a --- /dev/null +++ b/tools/getrepositorycontent/downloader.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "downloader.h" + +#include + +#include + +class ProxyFactory : public KDUpdater::FileDownloaderProxyFactory +{ +public: + ProxyFactory() {} + + ProxyFactory *clone() const + { + return new ProxyFactory(); + } + + QList queryProxy(const QNetworkProxyQuery &query = QNetworkProxyQuery()) + { + return QNetworkProxyFactory::systemProxyForQuery(query); + } +}; + +Downloader::Downloader(const QUrl &source, const QString &target) + : QObject() + , m_source(source) + , m_target(target) + , m_fileDownloader(0) +{ + m_fileDownloader = KDUpdater::FileDownloaderFactory::instance().create(m_source.scheme(), this); + m_fileDownloader->setDownloadedFileName(target); + + if (m_fileDownloader) { + m_fileDownloader->setUrl(m_source); + m_fileDownloader->setProxyFactory(new ProxyFactory()); + + connect(m_fileDownloader, SIGNAL(downloadCanceled()), this, SLOT(downloadFinished())); + connect(m_fileDownloader, SIGNAL(downloadCompleted()), this, SLOT(downloadFinished())); + connect(m_fileDownloader, SIGNAL(downloadAborted(QString)), this, SLOT(downloadFinished(QString))); + + connect(m_fileDownloader, SIGNAL(downloadSpeed(qint64)), this, SLOT(downloadSpeed(qint64))); + connect(m_fileDownloader, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(downloadProgress(qint64, qint64))); + + m_fileDownloader->setAutoRemoveDownloadedFile(false); + } + +} + +void Downloader::downloadFinished(const QString &message) +{ + if (!message.isEmpty()) + qDebug() << "Error:" << message; + progressBar.setStatus(100, 100); + progressBar.update(); + printf("\n"); + emit finished(); +} + +void Downloader::downloadSpeed(qint64 speed) +{ + progressBar.setMessage(QString::fromLatin1("%1 /sec").arg(QInstaller::humanReadableSize(speed))); +} + +void Downloader::downloadProgress(qint64 bytesReceived, qint64 bytesToReceive) +{ + if (bytesReceived == 0 || bytesToReceive == 0) + return; + progressBar.setStatus(bytesReceived, bytesToReceive); + progressBar.update(); +} + +void Downloader::run() +{ + m_fileDownloader->download(); +} diff --git a/tools/getrepositorycontent/downloader.h b/tools/getrepositorycontent/downloader.h new file mode 100644 index 000000000..bb4631bb9 --- /dev/null +++ b/tools/getrepositorycontent/downloader.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DOWNLOADER_H +#define DOWNLOADER_H + +#include "textprogressbar.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +class Downloader : public QObject +{ + Q_OBJECT +public: + explicit Downloader(const QUrl &source, const QString &target); + void run(); +signals: + void finished(); +private slots: + void downloadFinished(const QString &message = QString()); + void downloadSpeed(qint64 speed); + void downloadProgress(qint64 bytesReceived, qint64 bytesToReceive); + +private: + TextProgressBar progressBar; + QUrl m_source; + QString m_target; + KDUpdater::FileDownloader *m_fileDownloader; +}; + +#endif // DOWNLOADER_H diff --git a/tools/getrepositorycontent/getrepositorycontent.pro b/tools/getrepositorycontent/getrepositorycontent.pro new file mode 100644 index 000000000..d3412c63a --- /dev/null +++ b/tools/getrepositorycontent/getrepositorycontent.pro @@ -0,0 +1,22 @@ +TEMPLATE = app +INCLUDEPATH += . .. +TARGET = getrepositorycontent + +include(../../installerfw.pri) + +QT -= gui +QT += network + +CONFIG += console +DESTDIR = $$IFW_APP_PATH + +SOURCES += main.cpp \ + textprogressbar.cpp \ + downloader.cpp \ + domnodedebugstreamoperator.cpp + +HEADERS += \ + textprogressbar.h \ + downloader.h \ + domnodedebugstreamoperator.h + diff --git a/tools/getrepositorycontent/main.cpp b/tools/getrepositorycontent/main.cpp new file mode 100644 index 000000000..66a2ec43f --- /dev/null +++ b/tools/getrepositorycontent/main.cpp @@ -0,0 +1,450 @@ +/************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Installer Framework. +** +** $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 +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ + +#include "downloader.h" +#include "domnodedebugstreamoperator.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static void printUsage() +{ + const QString appName = QFileInfo( QCoreApplication::applicationFilePath() ).fileName(); + std::cout << "Usage: " << qPrintable(appName) + << " --url --repository --packages " << std::endl; + std::cout << " --url URL to fetch all the content from." << std::endl; + std::cout << " --repository Target directory for the repository content." << std::endl; + std::cout << " --packages The packages target directory where it creates the needed content to create new installers or repositories." << std::endl; + std::cout << " --clean Removes all the content if there is an existing repository or packages dir" << std::endl; + + std::cout << "Example:" << std::endl; + std::cout << " " << qPrintable(appName) << " --url http://www.example.com/repository/" << + " --repository repository --packages packages" << std::endl; +} + +// this should be a new class which uses XmlStreamReader instead of DomDocument +// should be implicit shared, see repository class +// maybe we can use some code from persistentdata in qtcreator +class ComponentData { + public: + ComponentData() {} + ComponentData(const QString &/*xmlData*/) {} + + QVariant attributeValue(const QString &key, const QString &attribute, const QVariant &defaultValue = QVariant()) { + Q_UNUSED(key) + Q_UNUSED(attribute) + return defaultValue; + } + + QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) { + Q_UNUSED(defaultValue) + // just use the quick dirty hack added members + if (key == QLatin1String("Script")) + return m_script; + if (key == QLatin1String("Version")) + return m_version; + return QVariant(); + } + QString textValue(const QString &key, const QString &defaultValue = QString()) { + return value(key, defaultValue).toString(); + } + + // quick dirty hack added public members + public: + QDomDocument m_packageXml; + QStringList m_downloadDownloadableArchives; + QString m_script; + QString m_version; +}; + +static void downloadFile(const QUrl &source, const QString &target) +{ + QEventLoop downloadEventLoop; + Downloader downloader(source, target); + QObject::connect(&downloader, SIGNAL(finished()), &downloadEventLoop, SLOT(quit())); + downloader.run(); + downloadEventLoop.exec(); +} + +QHash downLoadRepository(const QString &repositoryUrl, const QString &repositoryTarget) +{ + const QString updatesXmlFileName = QLatin1String("Updates.xml"); + QHash componentDataHash; + + const QUrl updatesXmlUrl(QString::fromLatin1("%1/%2").arg(repositoryUrl, updatesXmlFileName)); + + downloadFile(updatesXmlUrl, QDir(repositoryTarget).filePath(updatesXmlFileName)); + + QFile updatesFile(QDir(repositoryTarget).filePath(updatesXmlFileName)); + if (!updatesFile.exists()) { + qDebug() << "could not download the file:" << updatesXmlUrl.toString(); + return componentDataHash; + } else + qDebug() << "file downloaded to location:" << QDir(repositoryTarget).filePath(updatesXmlFileName); + if (!updatesFile.open(QIODevice::ReadOnly)) { + qDebug() << QString::fromLatin1("Could not open Updates.xml for reading: %1").arg(updatesFile + .errorString()) ; + return componentDataHash; + } + + QStringList ignoreTagList; + ignoreTagList << QLatin1String("Name"); + ignoreTagList << QLatin1String("ReleaseDate"); + ignoreTagList << QLatin1String("SHA1"); + ignoreTagList << QLatin1String("UpdateFile"); + QStringList fileTagList; + fileTagList << QLatin1String("DownloadableArchives"); + + + QDomDocument updatesXml; + QString error; + int line = 0; + int column = 0; + if (!updatesXml.setContent( &updatesFile, &error, &line, &column)) { + qWarning() << QString::fromLatin1("Could not parse component index: %1:%2: %3") + .arg(QString::number(line), QString::number(column), error); + return componentDataHash; + } + + QDomNode packageUpdateDomNode = updatesXml.firstChildElement(QLatin1String("Updates")).firstChildElement( + QLatin1String("PackageUpdate")); + while (!packageUpdateDomNode.isNull()) { + + if (packageUpdateDomNode.nodeName() == QLatin1String("PackageUpdate")) { + QDomNode packageUpdateEntry = packageUpdateDomNode.firstChild(); + QString currentPackageName; + ComponentData currentComponentData; + // creating the package.xml for later use + QDomElement currentNewPackageElement = currentComponentData.m_packageXml.createElement( + QLatin1String("Package")); + while (!packageUpdateEntry.isNull()) { + // do name first before ignore filters the name out + if (packageUpdateEntry.nodeName() == QLatin1String("Name")) { + currentPackageName = packageUpdateEntry.toElement().text(); + } + if (ignoreTagList.contains(packageUpdateEntry.nodeName())) { + packageUpdateEntry = packageUpdateEntry.nextSibling(); + continue; + } + if (packageUpdateEntry.nodeName() == QLatin1String("Script")) { + currentComponentData.m_script = packageUpdateEntry.toElement().text(); + } + if (packageUpdateEntry.nodeName() == QLatin1String("Version")) { + currentComponentData.m_version = packageUpdateEntry.toElement().text(); + currentComponentData.m_downloadDownloadableArchives.append( + currentComponentData.m_version + QLatin1String("meta.7z")); + } + + if (packageUpdateEntry.nodeName() == QLatin1String("DownloadableArchives")) { + QStringList tDownloadList = packageUpdateEntry.toElement().text().split( + QInstaller::commaRegExp(), QString::SkipEmptyParts); + foreach (const QString &download, tDownloadList) { + currentComponentData.m_downloadDownloadableArchives.append( + currentComponentData.m_version + download); + currentComponentData.m_downloadDownloadableArchives.append( + currentComponentData.m_version + download + QLatin1String(".sha1")); + } + } + + currentNewPackageElement.appendChild(packageUpdateEntry.cloneNode(true)); + packageUpdateEntry = packageUpdateEntry.nextSibling(); + } + currentComponentData.m_packageXml.appendChild(currentNewPackageElement); + Q_ASSERT(!currentComponentData.m_packageXml.toString().isEmpty()); + componentDataHash.insert(currentPackageName, currentComponentData); + } else { + qWarning() << QString::fromLatin1("Unknown elment '%1'").arg(packageUpdateDomNode.nodeName(), + QFileInfo(updatesXmlFileName).absoluteFilePath()); + } + packageUpdateDomNode = packageUpdateDomNode.nextSibling(); + } + + QHashIterator itComponentData(componentDataHash); + while (itComponentData.hasNext()) { + itComponentData.next(); + QString componentDirectory = QDir(repositoryTarget).filePath(itComponentData.key()); + if (!QDir().mkpath(componentDirectory)) + qWarning() << "couldn't create:" << componentDirectory; + + foreach (const QString &download, itComponentData.value().m_downloadDownloadableArchives) { + const QString fileTarget(componentDirectory + QDir::separator() + download); + const QUrl downloadUrl(repositoryUrl + QLatin1String("/") + itComponentData.key() + QLatin1String("/") + download); + downloadFile(downloadUrl, fileTarget); + } + } + return componentDataHash; +} + +bool extractFile(const QString &source, const QString &target) +{ + if (!Lib7z::isSupportedArchive(source)) { + qWarning() << source << "is not a supported archive"; + } + + QFile archive(source); + if (archive.open(QIODevice::ReadOnly)) { + try { + Lib7z::extractArchive(&archive, target); + } catch (const Lib7z::SevenZipException& e) { + qWarning() << QString::fromLatin1("Error while extracting %1: %2.").arg(source, e.message()); + return false; + } catch (...) { + qWarning() << QString::fromLatin1("Unknown exception caught while extracting %1.").arg(source); + return false; + } + } else { + qWarning() << QString::fromLatin1("Could not open %1 for reading: %2.").arg( + target, archive.errorString()); + return false; + } + return true; +} + + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + + // init installer to have the 7z lib initialized + QInstaller::init(); + // with the installer messagehandler we need to enable verbose to see QDebugs + QInstaller::setVerbose(true); + + QString repositoryUrl; + QString repositoryTarget; + QString packageDirectoryTarget; + bool clean = false; + QStringList args = app.arguments(); + QStringList::const_iterator itArgument = args.constBegin(); + itArgument++; // ignore the first one + if (itArgument == args.constEnd()) { + printUsage(); + return 0; + } + + for (; itArgument != args.constEnd(); ++itArgument) { + if (*itArgument == QString::fromLatin1("-h") || *itArgument == QString::fromLatin1("--help")) { + printUsage(); + return 0; + } else if (*itArgument == QString::fromLatin1("--clean")) { + clean = true; + } else if (*itArgument == QString::fromLatin1("-u") || *itArgument == QString::fromLatin1("--url")) { + ++itArgument; + if (itArgument == args.end()) { + printUsage(); + return -1; + } else { + repositoryUrl = *itArgument; + } + } else if (*itArgument == QString::fromLatin1("-r") || *itArgument == QString::fromLatin1("--repository")) { + ++itArgument; + if (itArgument == args.end()) { + printUsage(); + return -1; + } else { + repositoryTarget = *itArgument; + } + } else if (*itArgument == QString::fromLatin1("-p") || *itArgument == QString::fromLatin1("--packages")) { + ++itArgument; + if (itArgument == args.end()) { + printUsage(); + return -1; + } else { + packageDirectoryTarget = *itArgument; + } + } else { + qWarning() << QString::fromLatin1("Argument '%1' is unknown").arg(*itArgument); + printUsage(); + return 0; + } + } + if (repositoryTarget.isEmpty() || packageDirectoryTarget.isEmpty()) { + printUsage(); + return 0; + } else { + // resolve pathes + repositoryTarget = QFileInfo(repositoryTarget).absoluteFilePath(); + packageDirectoryTarget = QFileInfo(packageDirectoryTarget).absoluteFilePath(); + } + + foreach (const QString &target, QStringList() << repositoryTarget << packageDirectoryTarget) { + if (QFileInfo(target).exists()) { + if (clean) { + qDebug() << "removing directory:" << target; + QInstaller::removeDirectory(target, true); + } else if (!QDir(target).entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot).isEmpty()){ + qWarning() << QString::fromLatin1("The directory '%1' needs to be empty or just " + "add the --clean argument.").arg(target); + return EXIT_FAILURE; + } + } + + while (!QDir().mkpath(target)) { + qWarning() << QString::fromLatin1("Could not create %1").arg(target); + } + } + + QHash componentDataHash; + componentDataHash = downLoadRepository(repositoryUrl, repositoryTarget); + + // maybe in that case we should download the meta data to temp and + // get the downdloadable archives information from there later + if (packageDirectoryTarget.isEmpty()) + return EXIT_SUCCESS; + + QDirIterator itRepositoryFile(repositoryTarget, QDir::Files, QDirIterator::Subdirectories); + while (itRepositoryFile.hasNext()) { + QString currentFile = itRepositoryFile.next(); + + QString componentSubdirectoryName = itRepositoryFile.filePath(); + + QString normalizedRepositoryTarget = repositoryTarget; + normalizedRepositoryTarget.replace(QLatin1Char('\\'), QLatin1Char('/')); + + componentSubdirectoryName.remove(repositoryTarget); + componentSubdirectoryName.remove(normalizedRepositoryTarget); + + QString componentPackageDir = QFileInfo(packageDirectoryTarget + QDir::separator() + componentSubdirectoryName).absolutePath(); + QString absoluteSourceFilePath = itRepositoryFile.filePath(); + + if (currentFile.endsWith(QLatin1String("meta.7z"))) { + QString absolutTargetPath = QFileInfo( + packageDirectoryTarget + QDir::separator()).absolutePath(); + + extractFile(absoluteSourceFilePath, absolutTargetPath); + QInstaller::moveDirectoryContents(componentPackageDir, + componentPackageDir + QDir::separator() + QLatin1String("meta")); + } else if (!currentFile.endsWith(QLatin1String("Updates.xml")) && !currentFile.endsWith(QLatin1String(".sha1"))){ + QString pathToTarget = componentPackageDir + QDir::separator() + QLatin1String("data"); + QString target = QDir(pathToTarget).absoluteFilePath(itRepositoryFile.fileName()); + QDir().mkpath(pathToTarget); + QFile file; + if (!file.copy(absoluteSourceFilePath, target)) { + qWarning() << QString::fromLatin1("copy file %1 to %2 wasn't working %3").arg( + absoluteSourceFilePath, target, file.errorString()); + } + } + } + + + QHashIterator itComponentData(componentDataHash); + while (itComponentData.hasNext()) { + itComponentData.next(); + if (itComponentData.value().m_script.isEmpty()) + continue; + + QString componentScript = QFileInfo(QString::fromLatin1("%1/%2/meta/%3").arg( + packageDirectoryTarget, itComponentData.key(), itComponentData.value().m_script)).absoluteFilePath(); + + QString packagesXml = QFileInfo(QString::fromLatin1("%1/%2/meta/packages.xml").arg( + packageDirectoryTarget, itComponentData.key())).absoluteFilePath(); + + QFile packagesXmlFile(packagesXml); + + if (!packagesXmlFile.open(QIODevice::WriteOnly | QIODevice::Text)) { + qWarning() << QString::fromLatin1("Failed to open '%1' for writing. %2").arg( + packagesXml, packagesXmlFile.errorString()); + return EXIT_FAILURE; + } + + if (itComponentData.value().m_packageXml.toString().isEmpty()) { + qWarning() << "No xml data found in component:" << itComponentData.key(); + return EXIT_FAILURE; + } + + QTextStream stream(&packagesXmlFile); + stream << itComponentData.value().m_packageXml.toString(4); + packagesXmlFile.close(); + + QString dataPackagesPath = QFileInfo(QString::fromLatin1("%1/%2/data").arg( + packageDirectoryTarget, itComponentData.key())).absoluteFilePath(); + QDir().mkpath(dataPackagesPath); + + QString dataRepositoryPath = QFileInfo(repositoryTarget + QDir::separator() + itComponentData.key()).absoluteFilePath(); + QDir().mkpath(dataRepositoryPath); + + QFile componentScriptFile(componentScript); + if (!componentScriptFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + qDebug() << QString::fromLatin1("Can not read %1 %2").arg(componentScript, componentScriptFile.errorString()); + continue; + } + + QString sevenZString; + QTextStream in(&componentScriptFile); + in.setCodec("UTF-8"); + while (!in.atEnd()) { + QString line = in.readLine(); + if (line.contains(QLatin1String(".7z"))) { + int firstPosition = line.indexOf(QLatin1String("\"")); + QString subString = line.right(line.count() - firstPosition - 1); //-1 means " + //qDebug() << subString; + int secondPosition = subString.indexOf(QLatin1String("\"")); + sevenZString = subString.left(secondPosition); + QUrl downloadUrl((QStringList() << repositoryUrl << itComponentData.key() << itComponentData.value().m_version + sevenZString).join(QLatin1String("/"))); + QString localRepositoryTarget = dataRepositoryPath + QLatin1Char('/') + itComponentData.value().m_version + sevenZString; + downloadFile(downloadUrl, localRepositoryTarget); + downloadFile(downloadUrl.toString() + QLatin1String(".sha1"), localRepositoryTarget + QLatin1String(".sha1")); + QFile::copy(localRepositoryTarget, dataPackagesPath + QLatin1Char('/') + sevenZString); + } + } + } + + return 0; +} diff --git a/tools/getrepositorycontent/textprogressbar.cpp b/tools/getrepositorycontent/textprogressbar.cpp new file mode 100644 index 000000000..14faefd5e --- /dev/null +++ b/tools/getrepositorycontent/textprogressbar.cpp @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "textprogressbar.h" +#include +#include + +TextProgressBar::TextProgressBar() + : value(0), maximum(-1), iteration(0) +{ +} + +void TextProgressBar::clear() +{ + printf("\n"); + fflush(stdout); + + iteration = 0; + value = 0; + maximum = -1; +} + +void TextProgressBar::update() +{ + ++iteration; + + if (maximum > 0) { + // we know the maximum + // draw a progress bar + int percent = value * 100 / maximum; + int hashes = percent / 2; + + QByteArray progressbar(hashes, '#'); + if (percent % 2) + progressbar += '>'; + + printf("\r[%-50s] %3d%% %s ", + progressbar.constData(), + percent, + qPrintable(message)); + } else { + // we don't know the maximum, so we can't draw a progress bar + int center = (iteration % 48) + 1; // 50 spaces, minus 2 + QByteArray before(qMax(center - 2, 0), ' '); + QByteArray after(qMin(center + 2, 50), ' '); + + printf("\r[%s###%s] %s ", + before.constData(), after.constData(), qPrintable(message)); + } +} + +void TextProgressBar::setMessage(const QString &m) +{ + message = m; +} + +void TextProgressBar::setStatus(qint64 val, qint64 max) +{ + value = val; + maximum = max; +} diff --git a/tools/getrepositorycontent/textprogressbar.h b/tools/getrepositorycontent/textprogressbar.h new file mode 100644 index 000000000..6f01f0c84 --- /dev/null +++ b/tools/getrepositorycontent/textprogressbar.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TEXTPROGRESSBAR_H +#define TEXTPROGRESSBAR_H + +#include + +class TextProgressBar +{ +public: + TextProgressBar(); + + void clear(); + void update(); + void setMessage(const QString &message); + void setStatus(qint64 value, qint64 maximum); + +private: + QString message; + qint64 value; + qint64 maximum; + int iteration; +}; + +#endif -- cgit v1.2.3