diff --git a/src/plasma/package.cpp b/src/plasma/package.cpp index e1826311f..4fa5150ca 100644 --- a/src/plasma/package.cpp +++ b/src/plasma/package.cpp @@ -193,7 +193,8 @@ 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())) { + (package.path() == path() && package.metadata() == metadata()) || + d->hasCycle(package)) { return; } @@ -908,4 +909,27 @@ QString PackagePrivate::fallbackFilePath(const char *key, const QString &filenam } } +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 + const Plasma::Package *slowPackage = &package; + const Plasma::Package *fastPackage = &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->metadata().isValid() && fastPackage->d->fallbackPackage->d->fallbackPackage->metadata() == slowPackage->metadata())) { + return true; + } + fastPackage = fastPackage->d->fallbackPackage->d->fallbackPackage; + slowPackage = slowPackage->d->fallbackPackage; + } + return false; +} + } // Namespace diff --git a/src/plasma/private/package_p.h b/src/plasma/private/package_p.h index 786847506..ddf2bdb84 100644 --- a/src/plasma/private/package_p.h +++ b/src/plasma/private/package_p.h @@ -74,6 +74,7 @@ public: 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 structure; QString path;