Git commit f1bdf30501b87cb79806362a68c7515ba755275a by David Faure. Committed on 20/09/2015 at 10:26. Pushed by dfaure into branch 'master'.
KSycoca: change DB filename to include language and sha1 of the dirs it's built from. This will prevent sycoca-rebuild ping-pong if two apps with different settings would share the same file (and keep finding that it's wrong for them), and it fixes Albert's bug that "LANG=de kcmshell5 --list" doesn't show German translations for the strings coming from desktop files. To avoid migration issues, the old filename ksycoca5 is still provided, as a hardlink so that mmap works. REVIEW: 125279 BUGS: 340731, 335780 FIXED-IN: 5.15 M +18 -7 autotests/ksycocatest.cpp M +1 -1 docs/kbuildsycoca5/man-kbuildsycoca5.8.docbook M +16 -0 src/sycoca/kbuildsycoca.cpp M +15 -8 src/sycoca/ksycoca.cpp M +1 -0 src/sycoca/ksycoca.h http://commits.kde.org/kservice/f1bdf30501b87cb79806362a68c7515ba755275a diff --git a/autotests/ksycocatest.cpp b/autotests/ksycocatest.cpp index 7c2d91e..56a202f 100644 --- a/autotests/ksycocatest.cpp +++ b/autotests/ksycocatest.cpp @@ -18,6 +18,7 @@ */ #include <ksycoca.h> +#include <ksycoca_p.h> #include <QTemporaryDir> #include <QTest> #include <QDebug> @@ -27,6 +28,7 @@ #include <QSignalSpy> #include <QProcess> #include <kservice.h> +#include <kservicefactory_p.h> class KSycocaTest : public QObject { @@ -42,7 +44,11 @@ private Q_SLOTS: // we don't need the services dir -> ensure there isn't one, so we can check allResourceDirs below. QDir(servicesDir()).removeRecursively(); + QSignalSpy spy(KSycoca::self(), SIGNAL(databaseChanged(QStringList))); runKBuildSycoca(QProcessEnvironment::systemEnvironment()); + qDebug() << "waiting for signal"; + QVERIFY(spy.wait(10000)); + qDebug() << "got signal"; } void testAllResourceDirs(); void testOtherAppDir(); @@ -60,7 +66,6 @@ QTEST_MAIN(KSycocaTest) void KSycocaTest::runKBuildSycoca(const QProcessEnvironment &environment) { - QSignalSpy spy(KSycoca::self(), SIGNAL(databaseChanged(QStringList))); QProcess proc; const QString kbuildsycoca = QStandardPaths::findExecutable(KBUILDSYCOCA_EXENAME); QVERIFY(!kbuildsycoca.isEmpty()); @@ -72,15 +77,11 @@ void KSycocaTest::runKBuildSycoca(const QProcessEnvironment &environment) proc.waitForFinished(); QCOMPARE(proc.exitStatus(), QProcess::NormalExit); - - qDebug() << "waiting for signal"; - QVERIFY(spy.wait(10000)); - qDebug() << "got signal"; } void KSycocaTest::testAllResourceDirs() { - // Dirs that exist and dirs that don't exist, should both in allResourceDirs(). + // Dirs that exist and dirs that don't exist, should both be in allResourceDirs(). const QStringList dirs = KSycoca::self()->allResourceDirs(); QVERIFY2(dirs.contains(servicesDir()), qPrintable(dirs.join(','))); QVERIFY2(dirs.contains(serviceTypesDir()), qPrintable(dirs.join(','))); @@ -126,7 +127,17 @@ void KSycocaTest::testOtherAppDir() } #endif - QVERIFY(KService::serviceByStorageId("test_app_other.desktop")); + // This is still NOT available. kbuildsycoca created a different DB file, the one we read from hasn't changed. + // Changing XDG_DATA_DIRS at runtime isn't supported, so this test isn't doing what apps would do. + // The point however is that another app using different dirs cannot mess up our DB. + QVERIFY(!KService::serviceByStorageId("test_app_other.desktop")); + + // Check here what the other app would see, by creating another sycoca instance. + KSycoca otherAppSycoca; + // do what serviceByStorageId does: + otherAppSycoca.ensureCacheValid(); + QVERIFY(otherAppSycoca.d->serviceFactory()->findServiceByStorageId("test_app_other.desktop")); + QVERIFY(otherAppSycoca.d->m_databasePath != KSycoca::self()->d->m_databasePath); // check that they use a different filename } #include "ksycocatest.moc" diff --git a/docs/kbuildsycoca5/man-kbuildsycoca5.8.docbook b/docs/kbuildsycoca5/man-kbuildsycoca5.8.docbook index d7f8581..03add7a 100644 --- a/docs/kbuildsycoca5/man-kbuildsycoca5.8.docbook +++ b/docs/kbuildsycoca5/man-kbuildsycoca5.8.docbook @@ -166,7 +166,7 @@ Show version information. <title>Files</title> <variablelist> <varlistentry> -<term><filename><varname>cachedir</varname>/ksycoca5</filename></term> +<term><filename><varname>cachedir</varname>/ksycoca5_[lang]_[sha1-of-dirs]</filename></term> <listitem> <para>The KService cache generated by <command>kbuildsycoca5</command>. On Unix systems, <varname>cachedir</varname> is typically <filename class="directory"><envar>XDG_CONFIG_HOME</envar></filename></para> diff --git a/src/sycoca/kbuildsycoca.cpp b/src/sycoca/kbuildsycoca.cpp index d3328f0..ccb9350 100644 --- a/src/sycoca/kbuildsycoca.cpp +++ b/src/sycoca/kbuildsycoca.cpp @@ -448,6 +448,21 @@ bool KBuildSycoca::recreate(bool incremental) qCWarning(SYCOCA) << "ERROR writing database" << database.fileName() << ". Disk full?"; return false; } + + if (!m_globalDatabase) { + // Compatibility code for KF < 5.15: provide a ksycoca5 symlink after the filename change, for old apps to keep working during the upgrade + const QString oldSycoca = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + QLatin1String("/ksycoca5"); + if (QFile::exists(oldSycoca)) { + QFile::remove(oldSycoca); +#ifdef Q_OS_UNIX + if (::link(QFile::encodeName(path).constData(), QFile::encodeName(oldSycoca).constData()) != 0) { + QFile::copy(path, oldSycoca); + } +#else + QFile::copy(path, oldSycoca); +#endif + } + } } else { delete str; str = 0; @@ -615,6 +630,7 @@ quint32 KBuildSycoca::calcResourceHash(const QString &resourceSubDir, const QStr bool KBuildSycoca::checkGlobalHeader() { + // Since it's part of the filename, we are 99% sure that the locale and prefixes will match. const QString current_language = QLocale().bcp47Name(); const quint32 current_update_sig = KBuildSycoca::calcResourceHash(QStringLiteral("kservices5"), QStringLiteral("update_ksycoca")); const QString current_prefixes = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation).join(QString(QLatin1Char(':'))); diff --git a/src/sycoca/ksycoca.cpp b/src/sycoca/ksycoca.cpp index a2b7040..0035f97 100644 --- a/src/sycoca/ksycoca.cpp +++ b/src/sycoca/ksycoca.cpp @@ -43,6 +43,7 @@ #include <kservicetypefactory_p.h> #include <kservicegroupfactory_p.h> #include <kservicefactory_p.h> +#include <QCryptographicHash> #include "kbuildsycoca_p.h" #include "ksycocadevices_p.h" @@ -54,11 +55,6 @@ */ #define KSYCOCA_VERSION 302 -/** - * Sycoca file name, used internally (by kbuildsycoca) - */ -#define KSYCOCA_FILENAME "ksycoca5" - #if HAVE_MADVISE || HAVE_MMAP #include <sys/mman.h> // This #include was checked when looking for posix_madvise #endif @@ -684,17 +680,28 @@ quint32 KSycoca::updateSignature() QString KSycoca::absoluteFilePath(DatabaseType type) { + const QString paths = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation).join(QString(QLatin1Char(':'))); + QString suffix = QLatin1Char('_') + QLocale().bcp47Name(); + if (type == GlobalDatabase) { - QString path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QString::fromLatin1("kservices5/" KSYCOCA_FILENAME)); + const QString fileName = QStringLiteral("ksycoca5") + suffix; + QString path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kservices5/") + fileName); if (path.isEmpty()) { - return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QString::fromLatin1("/kservices5/" KSYCOCA_FILENAME); + return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/kservices5/") + fileName; } return path; } const QByteArray ksycoca_env = qgetenv("KDESYCOCA"); if (ksycoca_env.isEmpty()) { - return QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + QLatin1Char('/') + QString::fromLatin1(KSYCOCA_FILENAME); + const QByteArray pathHash = QCryptographicHash::hash(paths.toUtf8(), QCryptographicHash::Sha1); + suffix += QLatin1Char('_') + QString::fromLatin1(pathHash.toBase64()); + suffix.replace('/', '_'); +#ifdef Q_OS_WIN + suffix.replace(':', '_'); +#endif + const QString fileName = QStringLiteral("ksycoca5") + suffix; + return QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + QLatin1Char('/') + fileName; } else { return QFile::decodeName(ksycoca_env); } diff --git a/src/sycoca/ksycoca.h b/src/sycoca/ksycoca.h index 34a2f63..c0c3502 100644 --- a/src/sycoca/ksycoca.h +++ b/src/sycoca/ksycoca.h @@ -244,6 +244,7 @@ private: friend class KBuildSycoca; friend class Kded; friend class KSycocaPrivate; + friend class KSycocaTest; Q_DISABLE_COPY(KSycoca) KSycocaPrivate *const d; _______________________________________________ kde-doc-english mailing list [email protected] https://mail.kde.org/mailman/listinfo/kde-doc-english
