[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