let cancel sync and finish sync lambda be reusable methods
authorMatthieu Gallien <matthieu.gallien@nextcloud.com>
Fri, 30 Aug 2024 14:51:09 +0000 (16:51 +0200)
committerMatthieu Gallien <matthieu_gallien@yahoo.fr>
Thu, 12 Sep 2024 06:40:50 +0000 (08:40 +0200)
will enable implementation of other ways to interrupt sync after
discovery to get user feedback

Signed-off-by: Matthieu Gallien <matthieu.gallien@nextcloud.com>
src/libsync/syncengine.cpp
src/libsync/syncengine.h

index 21d6b0c8b6bc33df7699d92d7528cceb59ed16b4..eb114f553d2400266846c35bbe3de22acc0dbecf 100644 (file)
@@ -801,102 +801,6 @@ void SyncEngine::slotDiscoveryFinished()
     _progressInfo->_status = ProgressInfo::Reconcile;
     emit transmissionProgress(*_progressInfo);
 
-    //    qCInfo(lcEngine) << "Permissions of the root folder: " << _csync_ctx->remote.root_perms.toString();
-    auto finish = [this]{
-        auto databaseFingerprint = _journal->dataFingerprint();
-        // If databaseFingerprint is empty, this means that there was no information in the database
-        // (for example, upgrading from a previous version, or first sync, or server not supporting fingerprint)
-        if (!databaseFingerprint.isEmpty() && _discoveryPhase
-            && _discoveryPhase->_dataFingerprint != databaseFingerprint) {
-            qCInfo(lcEngine) << "data fingerprint changed, assume restore from backup" << databaseFingerprint << _discoveryPhase->_dataFingerprint;
-            restoreOldFiles(_syncItems);
-        }
-
-        if (_discoveryPhase->_anotherSyncNeeded && !_discoveryPhase->_filesNeedingScheduledSync.empty()) {
-            slotScheduleFilesDelayedSync();
-        } else if (_discoveryPhase->_anotherSyncNeeded && _anotherSyncNeeded == NoFollowUpSync) {
-            _anotherSyncNeeded = ImmediateFollowUp;
-        }
-
-        if (!_discoveryPhase->_filesUnscheduleSync.empty()) {
-            slotUnscheduleFilesDelayedSync();
-        }
-
-        if (_discoveryPhase->_hasDownloadRemovedItems && _discoveryPhase->_hasUploadErrorItems) {
-            for (const auto &item : qAsConst(_syncItems)) {
-                if (item->_instruction == CSYNC_INSTRUCTION_ERROR && item->_direction == SyncFileItem::Up) {
-                    item->_instruction = CSYNC_INSTRUCTION_IGNORE;
-                }
-            }
-            _anotherSyncNeeded = ImmediateFollowUp;
-        }
-
-        Q_ASSERT(std::is_sorted(_syncItems.begin(), _syncItems.end()));
-
-        qCInfo(lcEngine) << "#### Reconcile (aboutToPropagate) #################################################### " << _stopWatch.addLapTime(QStringLiteral("Reconcile (aboutToPropagate)")) << "ms";
-
-        _localDiscoveryPaths.clear();
-
-        // To announce the beginning of the sync
-        emit aboutToPropagate(_syncItems);
-
-        qCInfo(lcEngine) << "#### Reconcile (aboutToPropagate OK) #################################################### "<< _stopWatch.addLapTime(QStringLiteral("Reconcile (aboutToPropagate OK)")) << "ms";
-
-        // it's important to do this before ProgressInfo::start(), to announce start of new sync
-        _progressInfo->_status = ProgressInfo::Propagation;
-        emit transmissionProgress(*_progressInfo);
-        _progressInfo->startEstimateUpdates();
-
-        // post update phase script: allow to tweak stuff by a custom script in debug mode.
-        if (!qEnvironmentVariableIsEmpty("OWNCLOUD_POST_UPDATE_SCRIPT")) {
-    #ifndef NDEBUG
-            const QString script = qEnvironmentVariable("OWNCLOUD_POST_UPDATE_SCRIPT");
-
-            qCDebug(lcEngine) << "Post Update Script: " << script;
-            auto scriptArgs = script.split(QRegularExpression("\\s+"), Qt::SkipEmptyParts);
-            if (scriptArgs.size() > 0) {
-                const auto scriptExecutable = scriptArgs.takeFirst();
-                QProcess::execute(scriptExecutable, scriptArgs);
-            }
-#else
-            qCWarning(lcEngine) << "**** Attention: POST_UPDATE_SCRIPT installed, but not executed because compiled with NDEBUG";
-    #endif
-        }
-
-        // do a database commit
-        _journal->commit(QStringLiteral("post treewalk"));
-
-        _propagator = QSharedPointer<OwncloudPropagator>(
-            new OwncloudPropagator(_account, _localPath, _remotePath, _journal, _bulkUploadBlackList));
-        _propagator->setSyncOptions(_syncOptions);
-        connect(_propagator.data(), &OwncloudPropagator::itemCompleted,
-            this, &SyncEngine::slotItemCompleted);
-        connect(_propagator.data(), &OwncloudPropagator::progress,
-            this, &SyncEngine::slotProgress);
-        connect(_propagator.data(), &OwncloudPropagator::finished, this, &SyncEngine::slotPropagationFinished, Qt::QueuedConnection);
-        connect(_propagator.data(), &OwncloudPropagator::seenLockedFile, this, &SyncEngine::seenLockedFile);
-        connect(_propagator.data(), &OwncloudPropagator::touchedFile, this, &SyncEngine::slotAddTouchedFile);
-        connect(_propagator.data(), &OwncloudPropagator::insufficientLocalStorage, this, &SyncEngine::slotInsufficientLocalStorage);
-        connect(_propagator.data(), &OwncloudPropagator::insufficientRemoteStorage, this, &SyncEngine::slotInsufficientRemoteStorage);
-        connect(_propagator.data(), &OwncloudPropagator::newItem, this, &SyncEngine::slotNewItem);
-
-        // apply the network limits to the propagator
-        setNetworkLimits(_uploadLimit, _downloadLimit);
-
-        deleteStaleDownloadInfos(_syncItems);
-        deleteStaleUploadInfos(_syncItems);
-        deleteStaleErrorBlacklistEntries(_syncItems);
-        _journal->commit(QStringLiteral("post stale entry removal"));
-
-        // Emit the started signal only after the propagator has been set up.
-        if (_needsUpdate)
-            Q_EMIT started();
-
-        _propagator->start(std::move(_syncItems));
-
-        qCInfo(lcEngine) << "#### Post-Reconcile end #################################################### " << _stopWatch.addLapTime(QStringLiteral("Post-Reconcile Finished")) << "ms";
-    };
-
     const auto displayDialog = ConfigFile().promptDeleteFiles() && !_syncOptions.isCmd();
     if (!_hasNoneFiles && _hasRemoveFile && displayDialog) {
         qCInfo(lcEngine) << "All the files are going to be changed, asking the user";
@@ -907,27 +811,14 @@ void SyncEngine::slotDiscoveryFinished()
             }
         }
 
-        QPointer<QObject> guard = new QObject();
-        QPointer<QObject> self = this;
-        auto callback = [this, self, finish, guard](bool cancel) -> void {
-            // use a guard to ensure its only called once...
-            // qpointer to self to ensure we still exist
-            if (!guard || !self) {
-                return;
-            }
-            guard->deleteLater();
-            if (cancel) {
-                qCInfo(lcEngine) << "User aborted sync";
-                finalize(false);
-                return;
-            } else {
-                finish();
-            }
-        };
-        emit aboutToRemoveAllFiles(side >= 0 ? SyncFileItem::Down : SyncFileItem::Up, callback);
+        promptUserBeforePropagation([this, side](auto &&callback){
+                                        emit aboutToRemoveAllFiles(side >= 0 ? SyncFileItem::Down : SyncFileItem::Up, callback);
+                                    });
         return;
     }
-    finish();
+
+
+    finishSync();
 }
 
 void SyncEngine::slotCleanPollsJobAborted(const QString &error, const ErrorCategory errorCategory)
@@ -1104,6 +995,131 @@ void SyncEngine::restoreOldFiles(SyncFileItemVector &syncItems)
     }
 }
 
+void SyncEngine::cancelSyncOrContinue(bool cancel)
+{
+    if (cancel) {
+        qCInfo(lcEngine) << "User aborted sync";
+        finalize(false);
+    } else {
+        finishSync();
+    }
+}
+
+void SyncEngine::finishSync()
+{
+    auto databaseFingerprint = _journal->dataFingerprint();
+    // If databaseFingerprint is empty, this means that there was no information in the database
+    // (for example, upgrading from a previous version, or first sync, or server not supporting fingerprint)
+    if (!databaseFingerprint.isEmpty() && _discoveryPhase
+        && _discoveryPhase->_dataFingerprint != databaseFingerprint) {
+        qCInfo(lcEngine) << "data fingerprint changed, assume restore from backup" << databaseFingerprint << _discoveryPhase->_dataFingerprint;
+        restoreOldFiles(_syncItems);
+    }
+
+    if (_discoveryPhase && _discoveryPhase->_anotherSyncNeeded && !_discoveryPhase->_filesNeedingScheduledSync.empty()) {
+        slotScheduleFilesDelayedSync();
+    } else if (_discoveryPhase && _discoveryPhase->_anotherSyncNeeded && _anotherSyncNeeded == NoFollowUpSync) {
+        _anotherSyncNeeded = ImmediateFollowUp;
+    }
+
+    if (_discoveryPhase && !_discoveryPhase->_filesUnscheduleSync.empty()) {
+        slotUnscheduleFilesDelayedSync();
+    }
+
+    if (_discoveryPhase && _discoveryPhase->_hasDownloadRemovedItems && _discoveryPhase->_hasUploadErrorItems) {
+        for (const auto &item : qAsConst(_syncItems)) {
+            if (item->_instruction == CSYNC_INSTRUCTION_ERROR && item->_direction == SyncFileItem::Up) {
+                // item->_instruction = CSYNC_INSTRUCTION_IGNORE;
+            }
+        }
+        _anotherSyncNeeded = ImmediateFollowUp;
+    }
+
+    Q_ASSERT(std::is_sorted(_syncItems.begin(), _syncItems.end()));
+
+    qCInfo(lcEngine) << "#### Reconcile (aboutToPropagate) #################################################### " << _stopWatch.addLapTime(QStringLiteral("Reconcile (aboutToPropagate)")) << "ms";
+
+    _localDiscoveryPaths.clear();
+
+    // To announce the beginning of the sync
+    emit aboutToPropagate(_syncItems);
+
+    qCInfo(lcEngine) << "#### Reconcile (aboutToPropagate OK) #################################################### "<< _stopWatch.addLapTime(QStringLiteral("Reconcile (aboutToPropagate OK)")) << "ms";
+
+    // it's important to do this before ProgressInfo::start(), to announce start of new sync
+    _progressInfo->_status = ProgressInfo::Propagation;
+    emit transmissionProgress(*_progressInfo);
+    _progressInfo->startEstimateUpdates();
+
+           // post update phase script: allow to tweak stuff by a custom script in debug mode.
+    if (!qEnvironmentVariableIsEmpty("OWNCLOUD_POST_UPDATE_SCRIPT")) {
+#ifndef NDEBUG
+        const QString script = qEnvironmentVariable("OWNCLOUD_POST_UPDATE_SCRIPT");
+
+        qCDebug(lcEngine) << "Post Update Script: " << script;
+        auto scriptArgs = script.split(QRegularExpression("\\s+"), Qt::SkipEmptyParts);
+        if (scriptArgs.size() > 0) {
+            const auto scriptExecutable = scriptArgs.takeFirst();
+            QProcess::execute(scriptExecutable, scriptArgs);
+        }
+#else
+        qCWarning(lcEngine) << "**** Attention: POST_UPDATE_SCRIPT installed, but not executed because compiled with NDEBUG";
+#endif
+    }
+
+    // do a database commit
+    _journal->commit(QStringLiteral("post treewalk"));
+
+    _propagator = QSharedPointer<OwncloudPropagator>(
+        new OwncloudPropagator(_account, _localPath, _remotePath, _journal, _bulkUploadBlackList));
+    _propagator->setSyncOptions(_syncOptions);
+    connect(_propagator.data(), &OwncloudPropagator::itemCompleted,
+            this, &SyncEngine::slotItemCompleted);
+    connect(_propagator.data(), &OwncloudPropagator::progress,
+            this, &SyncEngine::slotProgress);
+    connect(_propagator.data(), &OwncloudPropagator::finished, this, &SyncEngine::slotPropagationFinished, Qt::QueuedConnection);
+    connect(_propagator.data(), &OwncloudPropagator::seenLockedFile, this, &SyncEngine::seenLockedFile);
+    connect(_propagator.data(), &OwncloudPropagator::touchedFile, this, &SyncEngine::slotAddTouchedFile);
+    connect(_propagator.data(), &OwncloudPropagator::insufficientLocalStorage, this, &SyncEngine::slotInsufficientLocalStorage);
+    connect(_propagator.data(), &OwncloudPropagator::insufficientRemoteStorage, this, &SyncEngine::slotInsufficientRemoteStorage);
+    connect(_propagator.data(), &OwncloudPropagator::newItem, this, &SyncEngine::slotNewItem);
+
+    // apply the network limits to the propagator
+    setNetworkLimits(_uploadLimit, _downloadLimit);
+
+    deleteStaleDownloadInfos(_syncItems);
+    deleteStaleUploadInfos(_syncItems);
+    deleteStaleErrorBlacklistEntries(_syncItems);
+    _journal->commit(QStringLiteral("post stale entry removal"));
+
+    // Emit the started signal only after the propagator has been set up.
+    if (_needsUpdate)
+        Q_EMIT started();
+
+    _propagator->start(std::move(_syncItems));
+
+    qCInfo(lcEngine) << "#### Post-Reconcile end #################################################### " << _stopWatch.addLapTime(QStringLiteral("Post-Reconcile Finished")) << "ms";
+}
+
+template <typename T>
+void SyncEngine::promptUserBeforePropagation(T &&lambda)
+{
+    QPointer<QObject> guard = new QObject();
+    QPointer<QObject> self = this;
+    auto callback = [this, self, guard](bool cancel) -> void {
+        // use a guard to ensure its only called once...
+        // qpointer to self to ensure we still exist
+        if (!guard || !self) {
+            return;
+        }
+        guard->deleteLater();
+
+        cancelSyncOrContinue(cancel);
+    };
+
+    lambda(callback);
+}
+
 void SyncEngine::slotAddTouchedFile(const QString &fn)
 {
     QElapsedTimer now;
index 2887c4bc1f65853cb5f16f0b10df930f49f921ba..278c5569dfd4bc422c6ac3671c811414b035eaa8 100644 (file)
@@ -361,6 +361,13 @@ private:
      */
     void restoreOldFiles(SyncFileItemVector &syncItems);
 
+    void cancelSyncOrContinue(bool cancel);
+
+    void finishSync();
+
+    template <typename T>
+    void promptUserBeforePropagation(T &&lambda);
+
     // true if there is at least one file which was not changed on the server
     bool _hasNoneFiles = false;