[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    KDE/kdelibs/kdecore
From:       David Faure <faure () kde ! org>
Date:       2010-11-26 23:28:30
Message-ID: 20101126232830.95E4CAC8A2 () svn ! kde ! org
[Download RAW message or body]

SVN commit 1201149 by dfaure:

Ensure that KStandardDirs always returns resolved paths (when $HOME or $KDEHOME is a \
symlink), even when returning paths that don't exist yet. Otherwise, via caches (the \
kstandarddirs one or in applications), we can end up with a different path once it \
does exist, and comparisons will fail (e.g. the one in \
KConfigPrivate::parseConfigFiles which detects the local file).

(So this fixes "kconfigtest testRevertAllEntries" when $HOME is a symlink, but has \
its own setup-independent unittest now)


 M  +22 -3     kernel/kstandarddirs.cpp  
 M  +33 -0     tests/kstandarddirstest.cpp  
 M  +1 -0      tests/kstandarddirstest.h  


--- trunk/KDE/kdelibs/kdecore/kernel/kstandarddirs.cpp #1201148:1201149
@@ -923,9 +923,28 @@
         return QFile::decodeName(realpath_buffer);
     }
 
-    if (!dirname.endsWith(QLatin1Char('/')))
-        return dirname + QLatin1Char('/');
-    return dirname;
+    // Does not exist yet; resolve symlinks in parent dirs then.
+    // This ensures that once the directory exists, it will still be resolved
+    // the same way, so that the general rule that KStandardDirs always returns
+    // canonical paths stays true, and app code can compare paths more easily.
+    QString dir = dirname;
+    if (!dir.endsWith(QLatin1Char('/')))
+        dir += QLatin1Char('/');
+    QString relative;
+    while (!KStandardDirs::exists(dir)) {
+        //qDebug() << "does not exist:" << dir;
+        const int pos = dir.lastIndexOf(QLatin1Char('/'), -2);
+        Q_ASSERT(pos > 0); // what? even "/" doesn't exist?
+        relative.prepend(dir.mid(pos+1)); // keep "subdir/"
+        dir = dir.left(pos+1);
+        Q_ASSERT(dir.endsWith(QLatin1Char('/')));
+    }
+    Q_ASSERT(!relative.isEmpty()); // infinite recursion ahead
+    if (!relative.isEmpty()) {
+        //qDebug() << "done, resolving" << dir << "and adding" << relative;
+        dir = realPath(dir) + relative;
+    }
+    return dir;
 #endif
 }
 
--- trunk/KDE/kdelibs/kdecore/tests/kstandarddirstest.cpp #1201148:1201149
@@ -26,6 +26,7 @@
 #include <kstandarddirs.h>
 #include <kconfig.h>
 #include <kglobal.h>
+#include <ktempdir.h>
 #include "config-prefix.h"
 #include <QtCore/QDebug>
 #include <kconfiggroup.h>
@@ -407,6 +408,38 @@
     localFile.remove();
 }
 
+void KStandarddirsTest::testSymlinkResolution()
+{
+#ifndef Q_OS_WIN
+    // This makes the save location for the david resource, \
"$HOME/.kde-unit-test/symlink/test/" +    // where symlink points to "real", and the \
subdir test will be created later +    // This used to confuse KStandardDirs and make \
it return unresolved paths, +    // and thus making comparisons fail later on in \
KConfig. +    const QString symlink = m_kdehome + "/symlink";
+    const QString expected = m_kdehome + "/real/test/";
+    QVERIFY(KTempDir::removeDir(m_kdehome + "/real"));
+    QVERIFY(QDir(m_kdehome).mkdir("real"));
+    QFile::remove(symlink);
+    QVERIFY(!QFile::exists(symlink));
+    QVERIFY(QFile::link("real", symlink));
+    QVERIFY(QFileInfo(symlink).isSymLink());
+    QVERIFY(!QFile::exists(expected));
+    KGlobal::dirs()->addResourceType("david", 0, "symlink/test");
+    QVERIFY(!QFile::exists(expected));
+    const QString saveLoc = KGlobal::dirs()->resourceDirs("david").first();
+    QVERIFY(!QFile::exists(expected));
+    // The issue at this point is that saveLoc does not actually exist yet.
+    QVERIFY(QDir(saveLoc).canonicalPath().isEmpty()); // this is why we can't use \
canonicalPath +    QVERIFY(!QFile::exists(saveLoc));
+    QCOMPARE(saveLoc, KStandardDirs::realPath(saveLoc)); // must be resolved
+    QCOMPARE(saveLoc, expected);
+    QVERIFY(QDir(m_kdehome).mkpath("real/test")); // KConfig calls mkdir on its own, \
we simulate that here +    const QString sameSaveLoc = \
KGlobal::dirs()->resourceDirs("david").first(); +    QCOMPARE(sameSaveLoc, saveLoc);
+    QCOMPARE(sameSaveLoc, KGlobal::dirs()->saveLocation("david"));
+#endif
+}
+
 #include <QThreadPool>
 #include <qtconcurrentrun.h>
 
--- trunk/KDE/kdelibs/kdecore/tests/kstandarddirstest.h #1201148:1201149
@@ -42,6 +42,7 @@
     void testAddResourceDir();
     void testSetXdgDataDirs();
     void testRestrictedResources();
+    void testSymlinkResolution();
     void testThreads();
 
 private:


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic