]> cloud.milkyroute.net Git - dolphin.git/commitdiff
Use the output of 'svn status' instead of doing a custom and error-prone .svn-parsing...
authorPeter Penz <peter.penz19@gmail.com>
Tue, 28 Jul 2009 22:04:00 +0000 (22:04 +0000)
committerPeter Penz <peter.penz19@gmail.com>
Tue, 28 Jul 2009 22:04:00 +0000 (22:04 +0000)
svn path=/trunk/KDE/kdebase/apps/; revision=1003845

src/revisioncontrolplugin.cpp
src/revisioncontrolplugin.h

index 1e19ddcf0e7e2b08c090fc3f79dc0bdc56cc0730..02a229d7cad05db85249647dcb31816f71c8eef3 100644 (file)
@@ -19,6 +19,8 @@
 
 #include "revisioncontrolplugin.h"
 
+#include <stdio.h>
+
 RevisionControlPlugin::RevisionControlPlugin()
 {
 }
@@ -46,7 +48,6 @@ RevisionControlPlugin::~RevisionControlPlugin()
 #include <QTextStream>
 
 SubversionPlugin::SubversionPlugin() :
-    m_retrievalDir(),
     m_revisionInfoHash(),
     m_updateAction(0),
     m_showLocalChangesAction(0),
@@ -98,27 +99,36 @@ QString SubversionPlugin::fileName() const
 bool SubversionPlugin::beginRetrieval(const QString& directory)
 {
     Q_ASSERT(directory.endsWith('/'));
-    m_retrievalDir = directory;
-    const QString path = directory + ".svn/text-base/";
-
-    QDir dir(path);
-    const QFileInfoList fileInfoList = dir.entryInfoList();
-    const int size = fileInfoList.size();
-    QString fileName;
-    for (int i = 0; i < size; ++i) {
-        const QFileInfo fileInfo = fileInfoList.at(i);
-        fileName = fileInfo.fileName();
-        // Remove the ".svn-base" postfix to be able to compare the filenames
-        // in a fast way in SubversionPlugin::revisionState().
-        fileName.chop(sizeof(".svn-base") / sizeof(char) - 1);
-        if (!fileName.isEmpty()) {
-            RevisionInfo info;
-            info.size = fileInfo.size();
-            info.timeStamp = fileInfo.lastModified();
-            m_revisionInfoHash.insert(directory + fileName, info);
+
+    const QString statusCommand = "svn status " + directory;
+    FILE* in = popen(statusCommand.toAscii().data(), "r");
+    if (in == 0) {
+        return false;
+    }
+
+    char buffer[1024];
+    while (fgets(buffer, sizeof(buffer), in) != 0) {
+        RevisionState state = NormalRevision;
+
+        switch (buffer[0]) {
+        case '?': state = UnversionedRevision; break;
+        case 'M': state = LocallyModifiedRevision; break;
+        case 'A': state = AddedRevision; break;
+        case 'D': state = RemovedRevision; break;
+        case 'C': state = ConflictingRevision; break;
+        default: break;
+        }
+
+        QString filePath(buffer);
+        int pos = filePath.indexOf('/');
+        const int length = filePath.length() - pos - 1;
+        filePath = filePath.mid(pos, length);
+        if (!filePath.isEmpty()) {
+            m_revisionInfoHash.insert(filePath, state);
         }
     }
-    return size > 0;
+    m_revisionInfoKeys = m_revisionInfoHash.keys();
+    return true;
 }
 
 void SubversionPlugin::endRetrieval()
@@ -128,30 +138,29 @@ void SubversionPlugin::endRetrieval()
 RevisionControlPlugin::RevisionState SubversionPlugin::revisionState(const KFileItem& item)
 {
     const QString itemUrl = item.localPath();
-    if (item.isDir()) {
-        QFile file(itemUrl + "/.svn");
-        if (file.open(QIODevice::ReadOnly)) {
-            file.close();
-            return RevisionControlPlugin::NormalRevision;
-        }
-    } else if (m_revisionInfoHash.contains(itemUrl)) {
-        const RevisionInfo info = m_revisionInfoHash.value(itemUrl);
-        const QDateTime localTimeStamp = item.time(KFileItem::ModificationTime).dateTime();
-        const QDateTime versionedTimeStamp = info.timeStamp;
-
-        if (localTimeStamp > versionedTimeStamp) {
-            if ((info.size != item.size()) || !equalRevisionContent(item.name())) {
-                return RevisionControlPlugin::LocallyModifiedRevision;
-            }
-        } else if (localTimeStamp < versionedTimeStamp) {
-            if ((info.size != item.size()) || !equalRevisionContent(item.name())) {
-                return RevisionControlPlugin::UpdateRequiredRevision;
+    if (m_revisionInfoHash.contains(itemUrl)) {
+        return m_revisionInfoHash.value(itemUrl);
+    }
+
+    if (!item.isDir()) {
+        // files that have not been listed by 'svn status' (= m_revisionInfoHash)
+        // are under revision control per definition
+        return NormalRevision;
+    }
+
+    // The item is a directory. Check whether an item listed by 'svn status' (= m_revisionInfoHash)
+    // is part of this directory. In this case a local modification should be indicated in the
+    // directory already.
+    foreach (const QString& key, m_revisionInfoKeys) {
+        if (key.startsWith(itemUrl)) {
+            const RevisionState state = m_revisionInfoHash.value(key);
+            if (state == LocallyModifiedRevision) {
+                return LocallyModifiedRevision;
             }
         }
-        return  RevisionControlPlugin::NormalRevision;
     }
 
-    return RevisionControlPlugin::UnversionedRevision;
+    return NormalRevision;
 }
 
 QList<QAction*> SubversionPlugin::contextMenuActions(const KFileItemList& items)
@@ -268,26 +277,3 @@ void SubversionPlugin::execSvnCommand(const QString& svnCommand)
         }
     }
 }
-
-bool SubversionPlugin::equalRevisionContent(const QString& name) const
-{
-    QFile localFile(m_retrievalDir + '/' + name);
-    if (!localFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
-        return false;
-    }
-
-    QFile revisionedFile(m_retrievalDir + "/.svn/text-base/" + name + ".svn-base");
-    if (!revisionedFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
-        return false;
-    }
-
-     QTextStream localText(&localFile);
-     QTextStream revisionedText(&revisionedFile);
-     while (!localText.atEnd() && !revisionedText.atEnd()) {
-         if (localText.readLine() != revisionedText.readLine()) {
-             return false;
-         }
-     }
-
-     return localText.atEnd() && revisionedText.atEnd();
-}
index 7863cfacb391b36e425131f92556224c436747fe..718e5c17d6500332fed41bc7aabdd2e881fb8eaf 100644 (file)
@@ -65,6 +65,11 @@ public:
          * has been marked to get added with the next commit.
          */
         AddedRevision,
+        /**
+         * The file is under revision control but has been marked
+         * for getting removed with the next commit.
+         */
+        RemovedRevision,
         /**
          * The file is under revision control and has been locally
          * modified. A modification has also been done on the main
@@ -171,21 +176,9 @@ private:
      */
     void execSvnCommand(const QString& svnCommand);
 
-    /**
-     * Returns true, if the content of the local file \p name is equal to the
-     * content of the revisioned file.
-     */
-    bool equalRevisionContent(const QString& name) const;
-
 private:
-    struct RevisionInfo
-    {
-        quint64 size;
-        QDateTime timeStamp;
-    };
-
-    QString m_retrievalDir;
-    QHash<QString, RevisionInfo> m_revisionInfoHash;
+    QHash<QString, RevisionState> m_revisionInfoHash;
+    QList<QString> m_revisionInfoKeys; // cache for accessing the keys of the hash
 
     QAction* m_updateAction;
     QAction* m_showLocalChangesAction;