[Pkg-owncloud-commits] [owncloud-client] 219/470: Move the SocketApi business logic to a libsync SyncFileStatusTracker class

Sandro Knauß hefee-guest at moszumanska.debian.org
Thu May 12 16:25:05 UTC 2016


This is an automated email from the git hooks/post-receive script.

hefee-guest pushed a commit to branch master
in repository owncloud-client.

commit da7b9916e52eefcc8f5ea7501213899d076fcfbe
Author: Jocelyn Turcotte <jturcotte at woboq.com>
Date:   Thu Mar 17 12:26:44 2016 +0100

    Move the SocketApi business logic to a libsync SyncFileStatusTracker class
    
    This will allow testing this code and avoid going through too many
    layers to get notified and a file status changed.
---
 src/gui/accountsettings.cpp           |   1 +
 src/gui/folder.cpp                    |  70 -----------
 src/gui/folder.h                      |  20 +--
 src/gui/socketapi.cpp                 | 149 +---------------------
 src/libsync/CMakeLists.txt            |   1 +
 src/libsync/syncengine.cpp            |   1 +
 src/libsync/syncengine.h              |   7 +-
 src/libsync/syncfilestatustracker.cpp | 230 ++++++++++++++++++++++++++++++++++
 src/libsync/syncfilestatustracker.h   |  51 ++++++++
 9 files changed, 296 insertions(+), 234 deletions(-)

diff --git a/src/gui/accountsettings.cpp b/src/gui/accountsettings.cpp
index 383751b..83756bf 100644
--- a/src/gui/accountsettings.cpp
+++ b/src/gui/accountsettings.cpp
@@ -34,6 +34,7 @@
 
 #include <QDebug>
 #include <QDesktopServices>
+#include <QDir>
 #include <QListWidgetItem>
 #include <QMessageBox>
 #include <QAction>
diff --git a/src/gui/folder.cpp b/src/gui/folder.cpp
index 272d544..9cc7aef 100644
--- a/src/gui/folder.cpp
+++ b/src/gui/folder.cpp
@@ -99,8 +99,6 @@ Folder::Folder(const FolderDefinition& definition,
     connect(_engine.data(), SIGNAL(rootEtag(QString)), this, SLOT(etagRetreivedFromSyncEngine(QString)));
     connect(_engine.data(), SIGNAL(treeWalkResult(const SyncFileItemVector&)),
               this, SLOT(slotThreadTreeWalkResult(const SyncFileItemVector&)), Qt::QueuedConnection);
-    connect(_engine.data(), SIGNAL(aboutToPropagate(SyncFileItemVector&)),
-              this, SLOT(slotAboutToPropagate(SyncFileItemVector&)));
 
     connect(_engine.data(), SIGNAL(started()),  SLOT(slotSyncStarted()), Qt::QueuedConnection);
     connect(_engine.data(), SIGNAL(finished(bool)), SLOT(slotSyncFinished(bool)), Qt::QueuedConnection);
@@ -595,71 +593,11 @@ void Folder::slotWatchedPathChanged(const QString& path)
     }
 }
 
-/**
- * Whether this item should get an ERROR icon through the Socket API.
- *
- * The Socket API should only present serious, permanent errors to the user.
- * In particular SoftErrors should just retain their 'needs to be synced'
- * icon as the problem is most likely going to resolve itself quickly and
- * automatically.
- */
-static bool showErrorInSocketApi(const SyncFileItem& item)
-{
-    const auto status = item._status;
-    return status == SyncFileItem::NormalError
-        || status == SyncFileItem::FatalError;
-}
-
-static void addErroredSyncItemPathsToList(const SyncFileItemVector& items, QSet<QString>* set) {
-    foreach (const SyncFileItemPtr &item, items) {
-        if (showErrorInSocketApi(*item)) {
-            set->insert(item->_file);
-        }
-    }
-}
-
 void Folder::slotThreadTreeWalkResult(const SyncFileItemVector& items)
 {
-    addErroredSyncItemPathsToList(items, &this->_stateLastSyncItemsWithErrorNew);
     _syncResult.setSyncFileItemVector(items);
 }
 
-void Folder::slotAboutToPropagate(SyncFileItemVector& items)
-{
-    addErroredSyncItemPathsToList(items, &this->_stateLastSyncItemsWithErrorNew);
-}
-
-
-bool Folder::estimateState(QString fn, csync_ftw_type_e t, SyncFileStatus* s)
-{
-    if (t == CSYNC_FTW_TYPE_DIR) {
-        if (Utility::doesSetContainPrefix(_stateLastSyncItemsWithError, fn)) {
-            qDebug() << Q_FUNC_INFO << "Folder has error" << fn;
-            s->set(SyncFileStatus::STATUS_ERROR);
-            return true;
-        }
-        // If sync is running, check _syncedItems, possibly give it STATUS_EVAL (=syncing down)
-        if (_engine->isSyncRunning()) {
-            if (_engine->estimateState(fn, t, s)) {
-                return true;
-            }
-        }
-        return false;
-    } else if ( t== CSYNC_FTW_TYPE_FILE) {
-        // check if errorList has the directory/file
-        if (Utility::doesSetContainPrefix(_stateLastSyncItemsWithError, fn)) {
-            s->set(SyncFileStatus::STATUS_ERROR);
-            return true;
-        }
-        // If sync running: _syncedItems -> SyncingState
-        if (_engine->isSyncRunning()) {
-            if (_engine->estimateState(fn, t, s)) {
-                return true;
-            }
-        }
-    }
-    return false;
-}
 
 void Folder::saveToSettings() const
 {
@@ -873,10 +811,6 @@ void Folder::slotSyncFinished(bool success)
 
 
 
-    // This is for sync state calculation
-    _stateLastSyncItemsWithError = _stateLastSyncItemsWithErrorNew;
-    _stateLastSyncItemsWithErrorNew.clear();
-
     if (_csyncError) {
         _syncResult.setStatus(SyncResult::Error);
         qDebug() << "  ** error Strings: " << _errors;
@@ -972,10 +906,6 @@ void Folder::slotTransmissionProgress(const ProgressInfo &pi)
 // a item is completed: count the errors and forward to the ProgressDispatcher
 void Folder::slotItemCompleted(const SyncFileItem &item, const PropagatorJob& job)
 {
-    if (showErrorInSocketApi(item)) {
-        _stateLastSyncItemsWithErrorNew.insert(item._file);
-    }
-
     if (Progress::isWarningKind(item._status)) {
         // Count all error conditions.
         _syncResult.setWarnCount(_syncResult.warnCount()+1);
diff --git a/src/gui/folder.h b/src/gui/folder.h
index 59fa7f6..a76b9e2 100644
--- a/src/gui/folder.h
+++ b/src/gui/folder.h
@@ -26,16 +26,9 @@
 
 #include <csync.h>
 
-#include <QDir>
-#include <QHash>
-#include <QSet>
 #include <QObject>
 #include <QStringList>
 
-#include <QDebug>
-#include <QTimer>
-#include <qelapsedtimer.h>
-
 class QThread;
 class QSettings;
 
@@ -181,8 +174,7 @@ public:
 
      // Used by the Socket API
      SyncJournalDb *journalDb() { return &_journal; }
-
-     bool estimateState(QString fn, csync_ftw_type_e t, SyncFileStatus* s);
+     SyncEngine &syncEngine() { return *_engine; }
 
      RequestEtagJob *etagJob() { return _requestEtagJob; }
      qint64 msecSinceLastSync() const { return _timeSinceLastSyncDone.elapsed(); }
@@ -262,7 +254,6 @@ private slots:
     void etagRetreived(const QString &);
     void etagRetreivedFromSyncEngine(const QString &);
 
-    void slotAboutToPropagate(SyncFileItemVector& );
     void slotThreadTreeWalkResult(const SyncFileItemVector& ); // after sync is done
 
     void slotEmitFinishedDelayed();
@@ -304,15 +295,6 @@ private:
     /// Reset when no follow-up is requested.
     int           _consecutiveFollowUpSyncs;
 
-    // SocketAPI: Cache files and folders that had errors so that they can
-    // get a red ERROR icon.
-    QSet<QString>   _stateLastSyncItemsWithErrorNew; // gets moved to _stateLastSyncItemsWithError at end of sync
-    QSet<QString>   _stateLastSyncItemsWithError;
-
-    // SocketAPI: A folder is tained if we got a file watcher notification
-    // for it. It's displayed as EVAL.
-    QSet<QString>   _stateTaintedFolders;
-
     SyncJournalDb _journal;
 
     ClientProxy   _clientProxy;
diff --git a/src/gui/socketapi.cpp b/src/gui/socketapi.cpp
index 39dc40f..b3c7161 100644
--- a/src/gui/socketapi.cpp
+++ b/src/gui/socketapi.cpp
@@ -23,6 +23,7 @@
 #include "utility.h"
 #include "theme.h"
 #include "syncjournalfilerecord.h"
+#include "syncengine.h"
 #include "syncfileitem.h"
 #include "filesystem.h"
 #include "version.h"
@@ -215,7 +216,7 @@ void SocketApi::slotUpdateFolderView(Folder *f)
                 f->syncResult().status() == SyncResult::SetupError ) {
 
             broadcastMessage(QLatin1String("STATUS"), f->path() ,
-                             this->fileStatus(f, "").toSocketAPIString());
+                             f->syncEngine().syncFileStatusTracker().fileStatus("").toSocketAPIString());
 
             broadcastMessage(QLatin1String("UPDATE_VIEW"), f->path() );
         } else {
@@ -235,7 +236,7 @@ void SocketApi::slotItemCompleted(const QString &folder, const SyncFileItem &ite
         return;
     }
 
-    auto status = this->fileStatus(f, item.destination());
+    auto status = f->syncEngine().syncFileStatusTracker().fileStatus(item.destination());
     const QString path = f->path() + item.destination();
     broadcastMessage(QLatin1String("STATUS"), path, status.toSocketAPIString());
 }
@@ -330,7 +331,7 @@ void SocketApi::command_RETRIEVE_FILE_STATUS(const QString& argument, QIODevice*
         statusString = QLatin1String("NOP");
     } else {
         const QString file = QDir::cleanPath(argument).mid(syncFolder->cleanPath().length()+1);
-        SyncFileStatus fileStatus = this->fileStatus(syncFolder, file);
+        SyncFileStatus fileStatus = syncFolder->syncEngine().syncFileStatusTracker().fileStatus(file);
 
         statusString = fileStatus.toSocketAPIString();
     }
@@ -367,7 +368,7 @@ void SocketApi::command_SHARE(const QString& localFile, QIODevice* socket)
     } else {
         const QString localFileClean = QDir::cleanPath(localFile);
         const QString file = localFileClean.mid(shareFolder->cleanPath().length()+1);
-        SyncFileStatus fileStatus = this->fileStatus(shareFolder, file);
+        SyncFileStatus fileStatus = shareFolder->syncEngine().syncFileStatusTracker().fileStatus(file);
 
         // Verify the file is on the server (to our knowledge of course)
         if (fileStatus.tag() != SyncFileStatus::STATUS_UPTODATE &&
@@ -423,7 +424,7 @@ void SocketApi::command_SHARE_STATUS(const QString &localFile, QIODevice *socket
         sendMessage(socket, message);
     } else {
         const QString file = QDir::cleanPath(localFile).mid(shareFolder->cleanPath().length()+1);
-        SyncFileStatus fileStatus = this->fileStatus(shareFolder, file);
+        SyncFileStatus fileStatus = shareFolder->syncEngine().syncFileStatusTracker().fileStatus(file);
 
         // Verify the file is on the server (to our knowledge of course)
         if (fileStatus.tag() != SyncFileStatus::STATUS_UPTODATE &&
@@ -478,142 +479,4 @@ QString SocketApi::buildRegisterPathMessage(const QString& path)
     return message;
 }
 
-/**
- * Get status about a single file.
- */
-SyncFileStatus SocketApi::fileStatus(Folder *folder, const QString& systemFileName)
-{
-    QString file = folder->path();
-    QString fileName = systemFileName.normalized(QString::NormalizationForm_C);
-    QString fileNameSlash = fileName;
-
-    if(fileName != QLatin1String("/") && !fileName.isEmpty()) {
-        file += fileName;
-    }
-
-    if( fileName.endsWith(QLatin1Char('/')) ) {
-        fileName.truncate(fileName.length()-1);
-        qDebug() << "Removed trailing slash: " << fileName;
-    } else {
-        fileNameSlash += QLatin1Char('/');
-    }
-
-    const QFileInfo fi(file);
-    if( !FileSystem::fileExists(file, fi) ) {
-        qDebug() << "OO File " << file << " is not existing";
-        return SyncFileStatus(SyncFileStatus::STATUS_STAT_ERROR);
-    }
-
-    // file is ignored?
-    // Qt considers .lnk files symlinks on Windows so we need to work
-    // around that here.
-    if( fi.isSymLink()
-#ifdef Q_OS_WIN
-            && fi.suffix() != "lnk"
-#endif
-            ) {
-        return SyncFileStatus(SyncFileStatus::STATUS_IGNORE);
-    }
-
-    csync_ftw_type_e type = CSYNC_FTW_TYPE_FILE;
-    if( fi.isDir() ) {
-        type = CSYNC_FTW_TYPE_DIR;
-    }
-
-    // Is it excluded?
-    if( folder->isFileExcludedRelative(fileName) ) {
-        return SyncFileStatus(SyncFileStatus::STATUS_IGNORE);
-    }
-
-    // Error if it is in the selective sync blacklist
-    foreach(const auto &s, folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList)) {
-        if (fileNameSlash.startsWith(s)) {
-            return SyncFileStatus(SyncFileStatus::STATUS_ERROR);
-        }
-    }
-
-    SyncFileStatus status(SyncFileStatus::STATUS_NONE);
-    SyncJournalFileRecord rec = folder->journalDb()->getFileRecord(fileName);
-
-    if (folder->estimateState(fileName, type, &status)) {
-        qDebug() << "Folder estimated status for" << fileName << "to" << status.toSocketAPIString();
-    } else if (fileName == "") {
-        // sync folder itself
-        switch (folder->syncResult().status()) {
-        case SyncResult::Undefined:
-        case SyncResult::NotYetStarted:
-        case SyncResult::SyncPrepare:
-        case SyncResult::SyncRunning:
-            status.set(SyncFileStatus::STATUS_EVAL);
-            return status;
-
-        case SyncResult::Success:
-        case SyncResult::Problem:
-            status.set(SyncFileStatus::STATUS_UPTODATE);
-            return status;
-
-        case SyncResult::Error:
-        case SyncResult::SetupError:
-        case SyncResult::SyncAbortRequested:
-            status.set(SyncFileStatus::STATUS_ERROR);
-            return status;
-
-        case SyncResult::Paused:
-            status.set(SyncFileStatus::STATUS_IGNORE);
-            return status;
-        }
-    } else if (type == CSYNC_FTW_TYPE_DIR) {
-        if (rec.isValid()) {
-            status.set(SyncFileStatus::STATUS_UPTODATE);
-        } else {
-            qDebug() << "Could not determine state for folder" << fileName << "will set STATUS_NEW";
-            status.set(SyncFileStatus::STATUS_NEW);
-        }
-    } else if (type == CSYNC_FTW_TYPE_FILE) {
-        if (rec.isValid()) {
-            if( FileSystem::getModTime(fi.absoluteFilePath()) == Utility::qDateTimeToTime_t(rec._modtime) ) {
-                status.set(SyncFileStatus::STATUS_UPTODATE);
-            } else {
-                if (rec._remotePerm.isNull() || rec._remotePerm.contains("W") ) {
-                    status.set(SyncFileStatus::STATUS_EVAL);
-                } else {
-                    status.set(SyncFileStatus::STATUS_ERROR);
-                }
-            }
-        } else {
-            qDebug() << "Could not determine state for file" << fileName << "will set STATUS_NEW";
-            status.set(SyncFileStatus::STATUS_NEW);
-        }
-    }
-
-    if (rec.isValid() && rec._remotePerm.contains("S"))
-        status.setSharedWithMe(true);
-
-    if (status.tag() == SyncFileStatus::STATUS_NEW) {
-        // check the parent folder if it is shared and if it is allowed to create a file/dir within
-        QDir d( fi.path() );
-        auto parentPath = d.path();
-        auto dirRec = folder->journalDb()->getFileRecord(parentPath);
-        bool isDir = type == CSYNC_FTW_TYPE_DIR;
-        while( !d.isRoot() && !(d.exists() && dirRec.isValid()) ) {
-            d.cdUp(); // returns true if the dir exists.
-
-            parentPath = d.path();
-            // cut the folder path
-            dirRec = folder->journalDb()->getFileRecord(parentPath);
-
-            isDir = true;
-        }
-        if( dirRec.isValid() && !dirRec._remotePerm.isNull()) {
-            if( (isDir && !dirRec._remotePerm.contains("K"))
-                    || (!isDir && !dirRec._remotePerm.contains("C")) ) {
-                status.set(SyncFileStatus::STATUS_ERROR);
-            }
-        }
-    }
-    return status;
-}
-
-
 } // namespace OCC
-
diff --git a/src/libsync/CMakeLists.txt b/src/libsync/CMakeLists.txt
index ca56c3e..328d538 100644
--- a/src/libsync/CMakeLists.txt
+++ b/src/libsync/CMakeLists.txt
@@ -56,6 +56,7 @@ set(libsync_SRCS
     propagateremotemkdir.cpp
     syncengine.cpp
     syncfilestatus.cpp
+    syncfilestatustracker.cpp
     syncjournaldb.cpp
     syncjournalfilerecord.cpp
     syncresult.cpp
diff --git a/src/libsync/syncengine.cpp b/src/libsync/syncengine.cpp
index 6e238cf..44864d9 100644
--- a/src/libsync/syncengine.cpp
+++ b/src/libsync/syncengine.cpp
@@ -93,6 +93,7 @@ SyncEngine::SyncEngine(AccountPtr account, const QString& localPath,
     csync_create(&_csync_ctx, localPath.toUtf8().data(), url_string.toUtf8().data());
     csync_init(_csync_ctx);
     _excludedFiles.reset(new ExcludedFiles(&_csync_ctx->excludes));
+    _syncFileStatusTracker.reset(new SyncFileStatusTracker(this));
 
     _thread.setObjectName("SyncEngine_Thread");
 }
diff --git a/src/libsync/syncengine.h b/src/libsync/syncengine.h
index b35cbe3..f78dad0 100644
--- a/src/libsync/syncengine.h
+++ b/src/libsync/syncengine.h
@@ -35,7 +35,7 @@
 #include "syncfileitem.h"
 #include "progressdispatcher.h"
 #include "utility.h"
-#include "syncfilestatus.h"
+#include "syncfilestatustracker.h"
 #include "accountfwd.h"
 #include "discoveryphase.h"
 #include "checksums.h"
@@ -75,10 +75,12 @@ public:
      * -1 means infinite
      */
     void setNewBigFolderSizeLimit(qint64 limit) { _newBigFolderSizeLimit = limit; }
+    bool ignoreHiddenFiles() const { return _csync_ctx->ignore_hidden_files; }
     void setIgnoreHiddenFiles(bool ignore) { _csync_ctx->ignore_hidden_files = ignore; }
 
     ExcludedFiles &excludedFiles() { return *_excludedFiles; }
     Utility::StopWatch &stopWatch() { return _stopWatch; }
+    SyncFileStatusTracker &syncFileStatusTracker() { return *_syncFileStatusTracker; }
 
     /* Return true if we detected that another sync is needed to complete the sync */
     bool isAnotherSyncNeeded() { return _anotherSyncNeeded; }
@@ -93,7 +95,7 @@ public:
 
     AccountPtr account() const;
     SyncJournalDb *journal() const { return _journal; }
-
+    QString localPath() const { return _localPath; }
     /**
      * Minimum age, in milisecond, of a file that can be uploaded.
      * Files more recent than that are not going to be uploaeded as they are considered
@@ -211,6 +213,7 @@ private:
     QScopedPointer<ProgressInfo> _progressInfo;
 
     QScopedPointer<ExcludedFiles> _excludedFiles;
+    QScopedPointer<SyncFileStatusTracker> _syncFileStatusTracker;
     Utility::StopWatch _stopWatch;
 
     // maps the origin and the target of the folders that have been renamed
diff --git a/src/libsync/syncfilestatustracker.cpp b/src/libsync/syncfilestatustracker.cpp
new file mode 100644
index 0000000..e88459b
--- /dev/null
+++ b/src/libsync/syncfilestatustracker.cpp
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) by Klaas Freitag <freitag at owncloud.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program 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 General Public License
+ * for more details.
+ */
+
+#include "syncfilestatustracker.h"
+#include "filesystem.h"
+#include "syncengine.h"
+#include "syncjournaldb.h"
+#include "syncjournalfilerecord.h"
+#include "utility.h"
+
+#include <QDir>
+#include <QFileInfo>
+
+namespace OCC {
+
+/**
+ * Whether this item should get an ERROR icon through the Socket API.
+ *
+ * The Socket API should only present serious, permanent errors to the user.
+ * In particular SoftErrors should just retain their 'needs to be synced'
+ * icon as the problem is most likely going to resolve itself quickly and
+ * automatically.
+ */
+static bool showErrorInSocketApi(const SyncFileItem& item)
+{
+    const auto status = item._status;
+    return status == SyncFileItem::NormalError
+        || status == SyncFileItem::FatalError;
+}
+
+static void addErroredSyncItemPathsToList(const SyncFileItemVector& items, QSet<QString>* set) {
+    foreach (const SyncFileItemPtr &item, items) {
+        if (showErrorInSocketApi(*item)) {
+            set->insert(item->_file);
+        }
+    }
+}
+
+SyncFileStatusTracker::SyncFileStatusTracker(SyncEngine *syncEngine)
+    : _syncEngine(syncEngine)
+{
+    connect(syncEngine, SIGNAL(treeWalkResult(const SyncFileItemVector&)),
+              this, SLOT(slotThreadTreeWalkResult(const SyncFileItemVector&)));
+    connect(syncEngine, SIGNAL(aboutToPropagate(SyncFileItemVector&)),
+              this, SLOT(slotAboutToPropagate(SyncFileItemVector&)));
+    connect(syncEngine, SIGNAL(finished(bool)), SLOT(slotSyncFinished()));
+    connect(syncEngine, SIGNAL(itemCompleted(const SyncFileItem &, const PropagatorJob &)),
+            this, SLOT(slotItemCompleted(const SyncFileItem &)));
+}
+
+bool SyncFileStatusTracker::estimateState(QString fn, csync_ftw_type_e t, SyncFileStatus* s)
+{
+    if (t == CSYNC_FTW_TYPE_DIR) {
+        if (Utility::doesSetContainPrefix(_stateLastSyncItemsWithError, fn)) {
+            qDebug() << Q_FUNC_INFO << "Folder has error" << fn;
+            s->set(SyncFileStatus::STATUS_ERROR);
+            return true;
+        }
+        // If sync is running, check _syncedItems, possibly give it STATUS_EVAL (=syncing down)
+        if (_syncEngine->isSyncRunning()) {
+            if (_syncEngine->estimateState(fn, t, s)) {
+                return true;
+            }
+        }
+        return false;
+    } else if ( t== CSYNC_FTW_TYPE_FILE) {
+        // check if errorList has the directory/file
+        if (Utility::doesSetContainPrefix(_stateLastSyncItemsWithError, fn)) {
+            s->set(SyncFileStatus::STATUS_ERROR);
+            return true;
+        }
+        // If sync running: _syncedItems -> SyncingState
+        if (_syncEngine->isSyncRunning()) {
+            if (_syncEngine->estimateState(fn, t, s)) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+
+/**
+ * Get status about a single file.
+ */
+SyncFileStatus SyncFileStatusTracker::fileStatus(const QString& systemFileName)
+{
+    QString file = _syncEngine->localPath();
+    QString fileName = systemFileName.normalized(QString::NormalizationForm_C);
+    QString fileNameSlash = fileName;
+
+    if(fileName != QLatin1String("/") && !fileName.isEmpty()) {
+        file += fileName;
+    }
+
+    if( fileName.endsWith(QLatin1Char('/')) ) {
+        fileName.truncate(fileName.length()-1);
+        qDebug() << "Removed trailing slash: " << fileName;
+    } else {
+        fileNameSlash += QLatin1Char('/');
+    }
+
+    const QFileInfo fi(file);
+    if( !FileSystem::fileExists(file, fi) ) {
+        qDebug() << "OO File " << file << " is not existing";
+        return SyncFileStatus(SyncFileStatus::STATUS_STAT_ERROR);
+    }
+
+    // file is ignored?
+    // Qt considers .lnk files symlinks on Windows so we need to work
+    // around that here.
+    if( fi.isSymLink()
+#ifdef Q_OS_WIN
+            && fi.suffix() != "lnk"
+#endif
+            ) {
+        return SyncFileStatus(SyncFileStatus::STATUS_IGNORE);
+    }
+
+    csync_ftw_type_e type = CSYNC_FTW_TYPE_FILE;
+    if( fi.isDir() ) {
+        type = CSYNC_FTW_TYPE_DIR;
+    }
+
+    // Is it excluded?
+    if( _syncEngine->excludedFiles().isExcluded(file, _syncEngine->localPath(), _syncEngine->ignoreHiddenFiles()) ) {
+        return SyncFileStatus(SyncFileStatus::STATUS_IGNORE);
+    }
+
+    // Error if it is in the selective sync blacklist
+    foreach(const auto &s, _syncEngine->journal()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList)) {
+        if (fileNameSlash.startsWith(s)) {
+            return SyncFileStatus(SyncFileStatus::STATUS_ERROR);
+        }
+    }
+
+    SyncFileStatus status(SyncFileStatus::STATUS_NONE);
+    SyncJournalFileRecord rec = _syncEngine->journal()->getFileRecord(fileName );
+
+    if (estimateState(fileName, type, &status)) {
+        qDebug() << "Folder estimated status for" << fileName << "to" << status.toSocketAPIString();
+    } else if (fileName == "") {
+        // sync folder itself
+        // FIXME: The new parent folder logic should take over this, treating the root the same as any folder.
+    } else if (type == CSYNC_FTW_TYPE_DIR) {
+        if (rec.isValid()) {
+            status.set(SyncFileStatus::STATUS_UPTODATE);
+        } else {
+            qDebug() << "Could not determine state for folder" << fileName << "will set STATUS_NEW";
+            status.set(SyncFileStatus::STATUS_NEW);
+        }
+    } else if (type == CSYNC_FTW_TYPE_FILE) {
+        if (rec.isValid()) {
+            if( FileSystem::getModTime(fi.absoluteFilePath()) == Utility::qDateTimeToTime_t(rec._modtime) ) {
+                status.set(SyncFileStatus::STATUS_UPTODATE);
+            } else {
+                if (rec._remotePerm.isNull() || rec._remotePerm.contains("W") ) {
+                    status.set(SyncFileStatus::STATUS_EVAL);
+                } else {
+                    status.set(SyncFileStatus::STATUS_ERROR);
+                }
+            }
+        } else {
+            qDebug() << "Could not determine state for file" << fileName << "will set STATUS_NEW";
+            status.set(SyncFileStatus::STATUS_NEW);
+        }
+    }
+
+    if (rec.isValid() && rec._remotePerm.contains("S"))
+        status.setSharedWithMe(true);
+
+    if (status.tag() == SyncFileStatus::STATUS_NEW) {
+        // check the parent folder if it is shared and if it is allowed to create a file/dir within
+        QDir d( fi.path() );
+        auto parentPath = d.path();
+        auto dirRec = _syncEngine->journal()->getFileRecord(parentPath);
+        bool isDir = type == CSYNC_FTW_TYPE_DIR;
+        while( !d.isRoot() && !(d.exists() && dirRec.isValid()) ) {
+            d.cdUp(); // returns true if the dir exists.
+
+            parentPath = d.path();
+            // cut the folder path
+            dirRec = _syncEngine->journal()->getFileRecord(parentPath);
+
+            isDir = true;
+        }
+        if( dirRec.isValid() && !dirRec._remotePerm.isNull()) {
+            if( (isDir && !dirRec._remotePerm.contains("K"))
+                    || (!isDir && !dirRec._remotePerm.contains("C")) ) {
+                status.set(SyncFileStatus::STATUS_ERROR);
+            }
+        }
+    }
+    return status;
+}
+
+void SyncFileStatusTracker::slotThreadTreeWalkResult(const SyncFileItemVector& items)
+{
+    addErroredSyncItemPathsToList(items, &_stateLastSyncItemsWithErrorNew);
+}
+
+void SyncFileStatusTracker::slotAboutToPropagate(SyncFileItemVector& items)
+{
+    addErroredSyncItemPathsToList(items, &_stateLastSyncItemsWithErrorNew);
+}
+
+void SyncFileStatusTracker::slotSyncFinished()
+{
+    _stateLastSyncItemsWithError = _stateLastSyncItemsWithErrorNew;
+    _stateLastSyncItemsWithErrorNew.clear();
+}
+
+void SyncFileStatusTracker::slotItemCompleted(const SyncFileItem &item)
+{
+    if (showErrorInSocketApi(item)) {
+        _stateLastSyncItemsWithErrorNew.insert(item._file);
+    }
+}
+
+}
diff --git a/src/libsync/syncfilestatustracker.h b/src/libsync/syncfilestatustracker.h
new file mode 100644
index 0000000..ac8a823
--- /dev/null
+++ b/src/libsync/syncfilestatustracker.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) by Klaas Freitag <freitag at owncloud.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program 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 General Public License
+ * for more details.
+ */
+
+#ifndef SYNCFILESTATUSTRACKER_H
+#define SYNCFILESTATUSTRACKER_H
+
+#include "ownsql.h"
+#include "syncfileitem.h"
+#include "syncfilestatus.h"
+#include <QSet>
+#include <csync.h>
+
+namespace OCC {
+
+class SyncEngine;
+
+class OWNCLOUDSYNC_EXPORT SyncFileStatusTracker : public QObject
+{
+public:
+    SyncFileStatusTracker(SyncEngine *syncEngine);
+    SyncFileStatus fileStatus(const QString& systemFileName);
+
+private slots:
+    void slotThreadTreeWalkResult(const SyncFileItemVector& items);
+    void slotAboutToPropagate(SyncFileItemVector& items);
+    void slotSyncFinished();
+    void slotItemCompleted(const SyncFileItem &item);
+
+private:
+    bool estimateState(QString fn, csync_ftw_type_e t, SyncFileStatus* s);
+
+    SyncEngine *_syncEngine;
+    // SocketAPI: Cache files and folders that had errors so that they can
+    // get a red ERROR icon.
+    QSet<QString>   _stateLastSyncItemsWithErrorNew; // gets moved to _stateLastSyncItemsWithError at end of sync
+    QSet<QString>   _stateLastSyncItemsWithError;
+};
+
+}
+
+#endif

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/owncloud-client.git



More information about the Pkg-owncloud-commits mailing list