Merge branch 'mart/packageFallback'
REVIEW:120029
This commit is contained in:
commit
8c8bd49130
@ -37,6 +37,7 @@ MACRO(PLASMA_UNIT_TESTS)
|
||||
ENDMACRO(PLASMA_UNIT_TESTS)
|
||||
|
||||
PLASMA_UNIT_TESTS(
|
||||
fallbackpackagetest
|
||||
packagestructuretest
|
||||
packageurlinterceptortest
|
||||
pluginloadertest
|
||||
|
7
autotests/data/testfallbackpackage/contents/ui/main.qml
Normal file
7
autotests/data/testfallbackpackage/contents/ui/main.qml
Normal file
@ -0,0 +1,7 @@
|
||||
import QtQuick 2.0
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
color: "darkblue"
|
||||
}
|
||||
|
15
autotests/data/testfallbackpackage/metadata.desktop
Normal file
15
autotests/data/testfallbackpackage/metadata.desktop
Normal file
@ -0,0 +1,15 @@
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
Keywords=
|
||||
Name=Test Fallback Package
|
||||
Type=Service
|
||||
|
||||
X-KDE-ParentApp=
|
||||
X-KDE-PluginInfo-Author=Marco Martin
|
||||
X-KDE-PluginInfo-Category=
|
||||
X-KDE-PluginInfo-Email=mart@kde.org
|
||||
X-KDE-PluginInfo-License=GPLv2+
|
||||
X-KDE-PluginInfo-Name=org.kde.testfallbackpackage
|
||||
X-KDE-PluginInfo-Version=
|
||||
X-KDE-PluginInfo-Website=
|
||||
X-Plasma-MainScript=ui/main.qml
|
7
autotests/data/testpackage/contents/ui/otherfile.qml
Normal file
7
autotests/data/testpackage/contents/ui/otherfile.qml
Normal file
@ -0,0 +1,7 @@
|
||||
import QtQuick 2.0
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
color: "darkblue"
|
||||
}
|
||||
|
71
autotests/fallbackpackagetest.cpp
Normal file
71
autotests/fallbackpackagetest.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2007 by Aaron Seigo <aseigo@kde.org> *
|
||||
* Copyright 2014 Marco Martin <mart@kde.org> *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public License *
|
||||
* along with this library; see the file COPYING.LIB. If not, write to *
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
|
||||
* Boston, MA 02110-1301, USA. *
|
||||
*******************************************************************************/
|
||||
|
||||
#include "fallbackpackagetest.h"
|
||||
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "packagestructure.h"
|
||||
#include "pluginloader.h"
|
||||
|
||||
void FallbackPackageTest::initTestCase()
|
||||
{
|
||||
m_fallPackagePath = QFINDTESTDATA("data/testpackage");
|
||||
m_fallbackPkg = Plasma::PluginLoader::self()->loadPackage("Plasma/Generic");
|
||||
m_fallbackPkg.setPath(m_fallPackagePath);
|
||||
|
||||
m_packagePath = QFINDTESTDATA("data/testfallbackpackage");
|
||||
m_pkg = Plasma::PluginLoader::self()->loadPackage("Plasma/Generic");
|
||||
m_pkg.setPath(m_packagePath);
|
||||
}
|
||||
|
||||
void FallbackPackageTest::beforeFallback()
|
||||
{
|
||||
QVERIFY(m_fallbackPkg.hasValidStructure());
|
||||
QVERIFY(m_pkg.hasValidStructure());
|
||||
|
||||
//m_fallbackPkg should have otherfile.qml, m_pkg shouldn't
|
||||
QVERIFY(!m_fallbackPkg.filePath("ui", "otherfile.qml").isEmpty());
|
||||
QVERIFY(m_pkg.filePath("ui", "otherfile.qml").isEmpty());
|
||||
}
|
||||
|
||||
void FallbackPackageTest::afterFallback()
|
||||
{
|
||||
m_pkg.setFallbackPackage(m_fallbackPkg);
|
||||
|
||||
//after setting the fallback, m_pkg should resolve the exact same file as m_fallbackPkg
|
||||
// for otherfile.qml
|
||||
QVERIFY(!m_pkg.filePath("ui", "otherfile.qml").isEmpty());
|
||||
QCOMPARE(m_fallbackPkg.filePath("ui", "otherfile.qml"), m_pkg.filePath("ui", "otherfile.qml"));
|
||||
QVERIFY(m_fallbackPkg.filePath("mainscript") != m_pkg.filePath("mainscript"));
|
||||
}
|
||||
|
||||
void FallbackPackageTest::cycle()
|
||||
{
|
||||
m_fallbackPkg.setFallbackPackage(m_pkg);
|
||||
m_pkg.setFallbackPackage(m_fallbackPkg);
|
||||
|
||||
//The cycle should have been detected and filePath should take a not infinite time
|
||||
QTRY_COMPARE_WITH_TIMEOUT(m_fallbackPkg.filePath("ui", "otherfile.qml"), m_pkg.filePath("ui", "otherfile.qml"), 1000);
|
||||
}
|
||||
|
||||
QTEST_MAIN(FallbackPackageTest)
|
||||
|
46
autotests/fallbackpackagetest.h
Normal file
46
autotests/fallbackpackagetest.h
Normal file
@ -0,0 +1,46 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2007 by Aaron Seigo <aseigo@kde.org> *
|
||||
* Copyright 2014 Marco Martin <mart@kde.org> *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public License *
|
||||
* along with this library; see the file COPYING.LIB. If not, write to *
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
|
||||
* Boston, MA 02110-1301, USA. *
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef FALLBACKPACKAGETEST_H
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
#include "plasma/package.h"
|
||||
|
||||
class FallbackPackageTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
void beforeFallback();
|
||||
void afterFallback();
|
||||
void cycle();
|
||||
|
||||
|
||||
private:
|
||||
Plasma::Package m_pkg;
|
||||
Plasma::Package m_fallbackPkg;
|
||||
QString m_packagePath;
|
||||
QString m_fallPackagePath;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -56,4 +56,3 @@ Comment[sv]=Plasma skalkomponenter
|
||||
Comment[uk]=Компоненти оболонки Плазми
|
||||
Comment[x-test]=xxPlasma Shell Componentsxx
|
||||
Comment[zh_TW]=Plasma Shell 組件
|
||||
|
||||
|
@ -49,6 +49,7 @@ Package::Package(PackageStructure *structure)
|
||||
: d(new PackagePrivate())
|
||||
{
|
||||
d->structure = structure;
|
||||
|
||||
if (d->structure) {
|
||||
d->structure.data()->initPackage(this);
|
||||
}
|
||||
@ -188,6 +189,27 @@ void Package::setDefaultPackageRoot(const QString &packageRoot)
|
||||
}
|
||||
}
|
||||
|
||||
void Package::setFallbackPackage(const Plasma::Package &package)
|
||||
{
|
||||
if ((d->fallbackPackage && d->fallbackPackage->path() == package.path() && d->fallbackPackage->metadata() == package.metadata()) ||
|
||||
//can't be fallback of itself
|
||||
(package.path() == path() && package.metadata() == metadata()) ||
|
||||
d->hasCycle(package)) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->fallbackPackage = new Package(package);
|
||||
}
|
||||
|
||||
Plasma::Package Package::fallbackPackage() const
|
||||
{
|
||||
if (d->fallbackPackage) {
|
||||
return (*d->fallbackPackage);
|
||||
} else {
|
||||
return Package();
|
||||
}
|
||||
}
|
||||
|
||||
QString Package::servicePrefix() const
|
||||
{
|
||||
return d->servicePrefix;
|
||||
@ -290,7 +312,7 @@ QString Package::filePath(const char *fileType, const QString &filename) const
|
||||
{
|
||||
if (!d->valid) {
|
||||
//qDebug() << "package is not valid";
|
||||
return QString();
|
||||
return d->fallbackFilePath(fileType, filename);
|
||||
}
|
||||
|
||||
const QString discoveryKey(fileType + filename);
|
||||
@ -305,7 +327,7 @@ QString Package::filePath(const char *fileType, const QString &filename) const
|
||||
//qDebug()<<d->contents.keys();
|
||||
if (!d->contents.contains(fileType)) {
|
||||
//qDebug() << "package does not contain" << fileType << filename;
|
||||
return QString();
|
||||
return d->fallbackFilePath(fileType, filename);
|
||||
}
|
||||
|
||||
paths = d->contents[fileType].paths;
|
||||
@ -313,7 +335,7 @@ QString Package::filePath(const char *fileType, const QString &filename) const
|
||||
if (paths.isEmpty()) {
|
||||
//qDebug() << "no matching path came of it, while looking for" << fileType << filename;
|
||||
d->discoveries.insert(discoveryKey, QString());
|
||||
return QString();
|
||||
return d->fallbackFilePath(fileType, filename);
|
||||
}
|
||||
} else {
|
||||
//when filetype is empty paths is always empty, so try with an empty string
|
||||
@ -356,7 +378,7 @@ QString Package::filePath(const char *fileType, const QString &filename) const
|
||||
}
|
||||
|
||||
//qDebug() << fileType << filename << "does not exist in" << prefixes << "at root" << d->path;
|
||||
return QString();
|
||||
return d->fallbackFilePath(fileType, filename);
|
||||
}
|
||||
|
||||
QStringList Package::entryList(const char *key) const
|
||||
@ -500,6 +522,7 @@ void Package::setPath(const QString &path)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if nothing did change, then we go back to the old dptr
|
||||
if (d->path == previousPath) {
|
||||
d = oldD;
|
||||
@ -511,6 +534,8 @@ void Package::setPath(const QString &path)
|
||||
delete d->metadata;
|
||||
d->metadata = 0;
|
||||
|
||||
QString fallback;
|
||||
|
||||
// uh-oh, but we didn't end up with anything valid, so we sadly reset ourselves
|
||||
// to futility.
|
||||
if (!d->valid) {
|
||||
@ -764,6 +789,7 @@ KJob *Package::uninstall(const QString &packageName, const QString &packageRoot)
|
||||
PackagePrivate::PackagePrivate()
|
||||
: QSharedData(),
|
||||
servicePrefix("plasma-applet-"),
|
||||
fallbackPackage(0),
|
||||
metadata(0),
|
||||
externalPaths(false),
|
||||
valid(false),
|
||||
@ -786,6 +812,7 @@ PackagePrivate::~PackagePrivate()
|
||||
dir.removeRecursively();
|
||||
}
|
||||
delete metadata;
|
||||
delete fallbackPackage;
|
||||
}
|
||||
|
||||
PackagePrivate &PackagePrivate::operator=(const PackagePrivate &rhs)
|
||||
@ -795,6 +822,11 @@ PackagePrivate &PackagePrivate::operator=(const PackagePrivate &rhs)
|
||||
}
|
||||
|
||||
structure = rhs.structure;
|
||||
if (rhs.fallbackPackage) {
|
||||
fallbackPackage = new Package(*rhs.fallbackPackage);
|
||||
} else {
|
||||
fallbackPackage = 0;
|
||||
}
|
||||
path = rhs.path;
|
||||
contentsPrefixPaths = rhs.contentsPrefixPaths;
|
||||
servicePrefix = rhs.servicePrefix;
|
||||
@ -874,4 +906,38 @@ void PackagePrivate::createPackageMetadata(const QString &path)
|
||||
metadata = new KPluginInfo(metadataPath);
|
||||
}
|
||||
|
||||
QString PackagePrivate::fallbackFilePath(const char *key, const QString &filename) const
|
||||
{
|
||||
//don't fallback if the package isn't valid and never fallback the metadata file
|
||||
if (qstrcmp(key, "metadata") != 0 && fallbackPackage && fallbackPackage->isValid()) {
|
||||
return fallbackPackage->filePath(key, filename);
|
||||
} else {
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
bool PackagePrivate::hasCycle(const Plasma::Package &package)
|
||||
{
|
||||
if (!package.d->fallbackPackage) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//This is the Floyd cycle detection algorithm
|
||||
//http://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare
|
||||
Plasma::Package *slowPackage = const_cast<Plasma::Package *>(&package);
|
||||
Plasma::Package *fastPackage = const_cast<Plasma::Package *>(&package);
|
||||
|
||||
while (fastPackage && fastPackage->d->fallbackPackage) {
|
||||
//consider two packages the same if they have the same metadata
|
||||
if ((fastPackage->d->fallbackPackage->metadata().isValid() && fastPackage->d->fallbackPackage->metadata() == slowPackage->metadata()) ||
|
||||
(fastPackage->d->fallbackPackage->d->fallbackPackage && fastPackage->d->fallbackPackage->d->fallbackPackage->metadata().isValid() && fastPackage->d->fallbackPackage->d->fallbackPackage->metadata() == slowPackage->metadata())) {
|
||||
qWarning() << "Warning: the fallback chain of " << package.metadata().pluginName() << "contains a cyclical dependency.";
|
||||
return true;
|
||||
}
|
||||
fastPackage = fastPackage->d->fallbackPackage->d->fallbackPackage;
|
||||
slowPackage = slowPackage->d->fallbackPackage;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // Namespace
|
||||
|
@ -290,6 +290,20 @@ public:
|
||||
*/
|
||||
void setDefaultPackageRoot(const QString &packageRoot);
|
||||
|
||||
/**
|
||||
* Sets the fallback package root path
|
||||
* If a file won't be found in this package, it will search it in the package
|
||||
* with the same structure identified by path
|
||||
* It is intended to be used by the packageStructure
|
||||
* @param path package root path @see setPath
|
||||
*/
|
||||
void setFallbackPackage(const Plasma::Package &package);
|
||||
|
||||
/**
|
||||
* @return The fallback package root path
|
||||
*/
|
||||
Plasma::Package fallbackPackage() const;
|
||||
|
||||
// Content structure description methods
|
||||
/**
|
||||
* @return all directories registered as part of this Package's structure
|
||||
@ -328,6 +342,7 @@ public:
|
||||
|
||||
private:
|
||||
QExplicitlySharedDataPointer<PackagePrivate> d;
|
||||
friend class PackagePrivate;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -73,6 +73,8 @@ public:
|
||||
void createPackageMetadata(const QString &path);
|
||||
QString unpack(const QString &filePath);
|
||||
void updateHash(const QString &basePath, const QString &subPath, const QDir &dir, QCryptographicHash &hash);
|
||||
QString fallbackFilePath(const char *key, const QString &filename = QString()) const;
|
||||
bool hasCycle(const Plasma::Package &package);
|
||||
|
||||
QWeakPointer<PackageStructure> structure;
|
||||
QString path;
|
||||
@ -82,6 +84,7 @@ public:
|
||||
QString servicePrefix;
|
||||
QHash<QString, QString> discoveries;
|
||||
QHash<QByteArray, ContentStructure> contents;
|
||||
Package *fallbackPackage;
|
||||
#ifndef PLASMA_NO_PACKAGE_EXTRADATA
|
||||
QStringList mimeTypes;
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user