From 5315246219ba9eac0c2876a09988b27005dd340c Mon Sep 17 00:00:00 2001 From: Matthieu Gallien Date: Fri, 13 Sep 2024 12:25:29 +0200 Subject: [PATCH] count the files deletion and warn if threshold is exceeded Signed-off-by: Matthieu Gallien --- src/libsync/configfile.cpp | 17 +++++++++++- src/libsync/configfile.h | 3 +++ src/libsync/syncengine.cpp | 55 +++++++++++++++++++++++++++++--------- src/libsync/syncengine.h | 2 ++ 4 files changed, 63 insertions(+), 14 deletions(-) diff --git a/src/libsync/configfile.cpp b/src/libsync/configfile.cpp index abc9eb8a84a6..671f4e71a27a 100644 --- a/src/libsync/configfile.cpp +++ b/src/libsync/configfile.cpp @@ -59,6 +59,7 @@ static constexpr char fullLocalDiscoveryIntervalC[] = "fullLocalDiscoveryInterva static constexpr char notificationRefreshIntervalC[] = "notificationRefreshInterval"; static constexpr char monoIconsC[] = "monoIcons"; static constexpr char promptDeleteC[] = "promptDeleteAllFiles"; +static constexpr char deleteFilesThresholdC[] = "deleteFilesThreshold"; static constexpr char crashReporterC[] = "crashReporter"; static constexpr char optionalServerNotificationsC[] = "optionalServerNotifications"; static constexpr char showCallNotificationsC[] = "showCallNotifications"; @@ -111,6 +112,8 @@ static constexpr char certPath[] = "http_certificatePath"; static constexpr char certPasswd[] = "http_certificatePasswd"; static const QSet validUpdateChannels { QStringLiteral("stable"), QStringLiteral("beta") }; + +static constexpr int deleteFilesThresholdDefaultValue = 100; } namespace OCC { @@ -1017,7 +1020,7 @@ bool ConfigFile::showMainDialogAsNormalWindow() const { bool ConfigFile::promptDeleteFiles() const { QSettings settings(configFile(), QSettings::IniFormat); - return settings.value(QLatin1String(promptDeleteC), false).toBool(); + return settings.value(QLatin1String(promptDeleteC), true).toBool(); } void ConfigFile::setPromptDeleteFiles(bool promptDeleteFiles) @@ -1026,6 +1029,18 @@ void ConfigFile::setPromptDeleteFiles(bool promptDeleteFiles) settings.setValue(QLatin1String(promptDeleteC), promptDeleteFiles); } +int ConfigFile::deleteFilesThreshold() const +{ + QSettings settings(configFile(), QSettings::IniFormat); + return settings.value(QLatin1String(deleteFilesThresholdC), deleteFilesThresholdDefaultValue).toInt(); +} + +void ConfigFile::setDeleteFilesThreshold(int thresholdValue) +{ + QSettings settings(configFile(), QSettings::IniFormat); + settings.setValue(QLatin1String(deleteFilesThresholdC), thresholdValue); +} + bool ConfigFile::monoIcons() const { QSettings settings(configFile(), QSettings::IniFormat); diff --git a/src/libsync/configfile.h b/src/libsync/configfile.h index 97ec16e2f5ad..440902635438 100644 --- a/src/libsync/configfile.h +++ b/src/libsync/configfile.h @@ -93,6 +93,9 @@ class OWNCLOUDSYNC_EXPORT ConfigFile [[nodiscard]] bool promptDeleteFiles() const; void setPromptDeleteFiles(bool promptDeleteFiles); + [[nodiscard]] int deleteFilesThreshold() const; + void setDeleteFilesThreshold(int thresholdValue); + [[nodiscard]] bool crashReporter() const; void setCrashReporter(bool enabled); diff --git a/src/libsync/syncengine.cpp b/src/libsync/syncengine.cpp index 086a025dee4f..2d99d46dd486 100644 --- a/src/libsync/syncengine.cpp +++ b/src/libsync/syncengine.cpp @@ -807,19 +807,7 @@ void SyncEngine::slotDiscoveryFinished() _progressInfo->_status = ProgressInfo::Reconcile; emit transmissionProgress(*_progressInfo); - const auto displayDialog = ConfigFile().promptDeleteFiles() && !_syncOptions.isCmd(); - if (!_hasNoneFiles && _hasRemoveFile && displayDialog) { - qCInfo(lcEngine) << "All the files are going to be changed, asking the user"; - int side = 0; // > 0 means more deleted on the server. < 0 means more deleted on the client - for (const auto &it : _syncItems) { - if (it->_instruction == CSYNC_INSTRUCTION_REMOVE) { - side += it->_direction == SyncFileItem::Down ? 1 : -1; - } - } - - promptUserBeforePropagation([this, side](auto &&callback){ - emit aboutToRemoveAllFiles(side >= 0 ? SyncFileItem::Down : SyncFileItem::Up, callback); - }); + if (handleMassDeletion()) { return; } @@ -1111,6 +1099,47 @@ void SyncEngine::finishSync() qCInfo(lcEngine) << "#### Post-Reconcile end #################################################### " << _stopWatch.addLapTime(QStringLiteral("Post-Reconcile Finished")) << "ms"; } +bool SyncEngine::handleMassDeletion() +{ + const auto displayDialog = ConfigFile().promptDeleteFiles() && !_syncOptions.isCmd(); + const auto allFilesDeleted = !_hasNoneFiles && _hasRemoveFile; + + auto deletionCounter = 0; + for (const auto &oneItem : qAsConst(_syncItems)) { + if (oneItem->_instruction == CSYNC_INSTRUCTION_REMOVE) { + if (oneItem->isDirectory()) { + const auto result = _journal->listFilesInPath(oneItem->_file.toUtf8(), [&deletionCounter] (const auto &oneRecord) { + if (oneRecord.isFile()) { + ++deletionCounter; + } + }); + if (!result) { + qCDebug(lcEngine()) << "unable to find the number of files within a deleted folder:" << oneItem->_file; + } + } else { + ++deletionCounter; + } + } + } + const auto filesDeletedThresholdExceeded = deletionCounter > ConfigFile().deleteFilesThreshold(); + + if ((allFilesDeleted || filesDeletedThresholdExceeded) && displayDialog) { + qCInfo(lcEngine) << "All the files are going to be changed, asking the user"; + int side = 0; // > 0 means more deleted on the server. < 0 means more deleted on the client + for (const auto &it : qAsConst(_syncItems)) { + if (it->_instruction == CSYNC_INSTRUCTION_REMOVE) { + side += it->_direction == SyncFileItem::Down ? 1 : -1; + } + } + + promptUserBeforePropagation([this, side](auto &&callback){ + emit aboutToRemoveAllFiles(side >= 0 ? SyncFileItem::Down : SyncFileItem::Up, callback); + }); + return true; + } + return false; +} + void SyncEngine::handleRemnantReadOnlyFolders() { promptUserBeforePropagation([this](auto &&callback) { diff --git a/src/libsync/syncengine.h b/src/libsync/syncengine.h index b0b26c5804bf..e934d5ed41d8 100644 --- a/src/libsync/syncengine.h +++ b/src/libsync/syncengine.h @@ -364,6 +364,8 @@ private slots: void finishSync(); + bool handleMassDeletion(); + void handleRemnantReadOnlyFolders(); template