diff options
-rw-r--r-- | src/csync/csync.cpp | 3 | ||||
-rw-r--r-- | src/csync/csync_private.h | 10 | ||||
-rw-r--r-- | src/csync/csync_update.cpp | 15 | ||||
-rw-r--r-- | src/gui/issueswidget.cpp | 5 | ||||
-rw-r--r-- | src/libsync/syncengine.cpp | 36 | ||||
-rw-r--r-- | src/libsync/syncengine.h | 12 | ||||
-rw-r--r-- | test/testsyncengine.cpp | 32 |
7 files changed, 75 insertions, 38 deletions
diff --git a/src/csync/csync.cpp b/src/csync/csync.cpp index 992e60f21..4474ef0e9 100644 --- a/src/csync/csync.cpp +++ b/src/csync/csync.cpp @@ -310,9 +310,6 @@ int csync_s::reinitialize() { renames.folder_renamed_from.clear(); renames.folder_renamed_to.clear(); - local_discovery_style = LocalDiscoveryStyle::FilesystemOnly; - locally_touched_dirs.clear(); - status = CSYNC_STATUS_INIT; SAFE_FREE(error_string); diff --git a/src/csync/csync_private.h b/src/csync/csync_private.h index f73a1b2d5..1e394e4dc 100644 --- a/src/csync/csync_private.h +++ b/src/csync/csync_private.h @@ -190,15 +190,7 @@ struct OCSYNC_EXPORT csync_s { */ bool read_remote_from_db = false; - LocalDiscoveryStyle local_discovery_style = LocalDiscoveryStyle::FilesystemOnly; - - /** - * List of folder-relative directory paths that should be scanned on the - * filesystem if the local_discovery_style suggests it. - * - * Their parents will be scanned too. The paths don't start with a /. - */ - std::set<QByteArray> locally_touched_dirs; + std::function<bool(const QByteArray &)> should_discover_locally_fn; bool ignore_hidden_files = true; diff --git a/src/csync/csync_update.cpp b/src/csync/csync_update.cpp index 9ce636476..12ede9161 100644 --- a/src/csync/csync_update.cpp +++ b/src/csync/csync_update.cpp @@ -569,23 +569,12 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn, bool do_read_from_db = (ctx->current == REMOTE_REPLICA && ctx->remote.read_from_db); const char *db_uri = uri; - if (ctx->current == LOCAL_REPLICA - && ctx->local_discovery_style == LocalDiscoveryStyle::DatabaseAndFilesystem) { + if (ctx->current == LOCAL_REPLICA && ctx->should_discover_locally_fn) { const char *local_uri = uri + strlen(ctx->local.uri); if (*local_uri == '/') ++local_uri; db_uri = local_uri; - do_read_from_db = true; - - // Minor bug: local_uri doesn't have a trailing /. Example: Assume it's "d/foo" - // and we want to check whether we should read from the db. Assume "d/foo a" is - // in locally_touched_dirs. Then this check will say no, don't read from the db! - // (because "d/foo" < "d/foo a" < "d/foo/bar") - // C++14: Could skip the conversion to QByteArray here. - auto it = ctx->locally_touched_dirs.lower_bound(QByteArray(local_uri)); - if (it != ctx->locally_touched_dirs.end() && it->startsWith(local_uri)) { - do_read_from_db = false; - } + do_read_from_db = !ctx->should_discover_locally_fn(QByteArray(local_uri)); } if (!depth) { diff --git a/src/gui/issueswidget.cpp b/src/gui/issueswidget.cpp index b49afb9c2..15de3f107 100644 --- a/src/gui/issueswidget.cpp +++ b/src/gui/issueswidget.cpp @@ -222,7 +222,6 @@ void IssuesWidget::slotProgressInfo(const QString &folder, const ProgressInfo &p return; const auto &engine = f->syncEngine(); const auto style = engine.lastLocalDiscoveryStyle(); - const auto &discoveryDirs = engine.currentLocalDiscoveryDirs(); cleanItems([&](QTreeWidgetItem *item) { if (ProtocolItem::folderName(item) != folder) return false; @@ -239,9 +238,7 @@ void IssuesWidget::slotProgressInfo(const QString &folder, const ProgressInfo &p if (path == ".") path.clear(); - // TODO: This logic has to match csync_ftw's - auto it = discoveryDirs.lower_bound(path); - return it != discoveryDirs.end() && it->startsWith(path); + return engine.shouldDiscoverLocally(path); }); } } diff --git a/src/libsync/syncengine.cpp b/src/libsync/syncengine.cpp index 958df186c..0361d4a60 100644 --- a/src/libsync/syncengine.cpp +++ b/src/libsync/syncengine.cpp @@ -860,7 +860,11 @@ void SyncEngine::startSync() _excludedFiles->setExcludeConflictFiles(!_account->capabilities().uploadConflictFiles()); _csync_ctx->read_remote_from_db = true; - _lastLocalDiscoveryStyle = _csync_ctx->local_discovery_style; + + _lastLocalDiscoveryStyle = _localDiscoveryStyle; + _csync_ctx->should_discover_locally_fn = [this](const QByteArray &path) { + return shouldDiscoverLocally(path); + }; bool ok; auto selectiveSyncBlackList = _journal->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, &ok); @@ -1084,6 +1088,7 @@ void SyncEngine::slotDiscoveryJobFinished(int discoveryResult) // Re-init the csync context to free memory _csync_ctx->reinitialize(); + _localDiscoveryPaths.clear(); // To announce the beginning of the sync emit aboutToPropagate(syncItems); @@ -1225,6 +1230,8 @@ void SyncEngine::finalize(bool success) _temporarilyUnavailablePaths.clear(); _renamedFolders.clear(); _uniqueErrors.clear(); + _localDiscoveryPaths.clear(); + _localDiscoveryStyle = LocalDiscoveryStyle::FilesystemOnly; _clearTouchedFilesTimer.start(); } @@ -1631,13 +1638,32 @@ AccountPtr SyncEngine::account() const void SyncEngine::setLocalDiscoveryOptions(LocalDiscoveryStyle style, std::set<QByteArray> dirs) { - _csync_ctx->local_discovery_style = style; - _csync_ctx->locally_touched_dirs = std::move(dirs); + _localDiscoveryStyle = style; + _localDiscoveryPaths = std::move(dirs); } -const std::set<QByteArray> &SyncEngine::currentLocalDiscoveryDirs() const +bool SyncEngine::shouldDiscoverLocally(const QByteArray &path) const { - return _csync_ctx->locally_touched_dirs; + if (_localDiscoveryStyle == LocalDiscoveryStyle::FilesystemOnly) + return true; + + auto it = _localDiscoveryPaths.lower_bound(path); + if (it == _localDiscoveryPaths.end() || !it->startsWith(path)) + return false; + + // maybe an exact match or an empty path? + if (it->size() == path.size() || path.isEmpty()) + return true; + + // check for a prefix + / match + forever { + if (it->size() > path.size() && it->at(path.size()) == '/') + return true; + ++it; + if (it == _localDiscoveryPaths.end() || !it->startsWith(path)) + return false; + } + return false; } void SyncEngine::abort() diff --git a/src/libsync/syncengine.h b/src/libsync/syncengine.h index 8e3bb5b86..aba6164de 100644 --- a/src/libsync/syncengine.h +++ b/src/libsync/syncengine.h @@ -114,11 +114,13 @@ public: void setLocalDiscoveryOptions(LocalDiscoveryStyle style, std::set<QByteArray> dirs = {}); /** - * Access the dirs that shall be rediscovered for DatabaseAndFilesystem discovery. + * Returns whether the given folder-relative path should be locally discovered + * given the local discovery options. * - * This is only valid during Discovery and Reconcile phases of the sync run. + * Example: If path is 'foo/bar' and style is DatabaseAndFilesystem and dirs contains + * 'foo/bar/touched_file', then the result will be true. */ - const std::set<QByteArray> ¤tLocalDiscoveryDirs() const; + bool shouldDiscoverLocally(const QByteArray &path) const; /** Access the last sync run's local discovery style */ LocalDiscoveryStyle lastLocalDiscoveryStyle() const { return _lastLocalDiscoveryStyle; } @@ -308,7 +310,9 @@ private: QSet<QString> _uniqueErrors; /** The kind of local discovery the last sync run used */ - LocalDiscoveryStyle _lastLocalDiscoveryStyle = LocalDiscoveryStyle::DatabaseAndFilesystem; + LocalDiscoveryStyle _lastLocalDiscoveryStyle = LocalDiscoveryStyle::FilesystemOnly; + LocalDiscoveryStyle _localDiscoveryStyle = LocalDiscoveryStyle::FilesystemOnly; + std::set<QByteArray> _localDiscoveryPaths; }; } diff --git a/test/testsyncengine.cpp b/test/testsyncengine.cpp index 6ac5ed549..10644abd0 100644 --- a/test/testsyncengine.cpp +++ b/test/testsyncengine.cpp @@ -605,6 +605,38 @@ private slots: QCOMPARE(fakeFolder.syncEngine().lastLocalDiscoveryStyle(), LocalDiscoveryStyle::FilesystemOnly); } + void testLocalDiscoveryDecision() + { + FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() }; + auto &engine = fakeFolder.syncEngine(); + + QVERIFY(engine.shouldDiscoverLocally("")); + QVERIFY(engine.shouldDiscoverLocally("A")); + QVERIFY(engine.shouldDiscoverLocally("A/X")); + + fakeFolder.syncEngine().setLocalDiscoveryOptions( + LocalDiscoveryStyle::DatabaseAndFilesystem, + { "A/X", "foo bar space/touch", "foo/", "zzz" }); + + QVERIFY(engine.shouldDiscoverLocally("")); + QVERIFY(engine.shouldDiscoverLocally("A")); + QVERIFY(engine.shouldDiscoverLocally("A/X")); + QVERIFY(!engine.shouldDiscoverLocally("B")); + QVERIFY(!engine.shouldDiscoverLocally("A B")); + QVERIFY(!engine.shouldDiscoverLocally("B/X")); + QVERIFY(!engine.shouldDiscoverLocally("A/X/Y")); + QVERIFY(engine.shouldDiscoverLocally("foo bar space")); + QVERIFY(engine.shouldDiscoverLocally("foo")); + QVERIFY(!engine.shouldDiscoverLocally("foo bar")); + QVERIFY(!engine.shouldDiscoverLocally("foo bar/touch")); + + fakeFolder.syncEngine().setLocalDiscoveryOptions( + LocalDiscoveryStyle::DatabaseAndFilesystem, + {}); + + QVERIFY(!engine.shouldDiscoverLocally("")); + } + void testDiscoveryHiddenFile() { FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() }; |