diff --git a/changelog/unreleased/8836 b/changelog/unreleased/8836 new file mode 100644 index 00000000000..c78993607a1 --- /dev/null +++ b/changelog/unreleased/8836 @@ -0,0 +1,8 @@ +Bugfix: Always exclude .owncloud files + +Our Linux virtual files implementation is using the file name extension .owncloud +those files where only ignored if the Linux VFS was enabled. +Under some circumstances it could lead to undefined client states. +We now always ignore those files as system reserved. + +https://github.com/owncloud/client/pull/8836 diff --git a/src/csync/csync_exclude.cpp b/src/csync/csync_exclude.cpp index f4747bb8d30..d618728fe86 100644 --- a/src/csync/csync_exclude.cpp +++ b/src/csync/csync_exclude.cpp @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" #include "config_csync.h" #ifndef _GNU_SOURCE @@ -154,6 +155,10 @@ static CSYNC_EXCLUDE_TYPE _csync_excluded_common(const QStringRef &path, bool ex } } + if (bname.endsWith(QLatin1String(APPLICATION_DOTVIRTUALFILE_SUFFIX), Qt::CaseInsensitive)) { // ".owncloud" placeholder + return CSYNC_FILE_EXCLUDE_RESERVED; + } + // check the strlen and ignore the file if its name is longer than 254 chars. // whenever changing this also check createDownloadTmpFileName if (blen > 254) { diff --git a/src/csync/csync_exclude.h b/src/csync/csync_exclude.h index 8cc3a318c6f..75b47bcbe3a 100644 --- a/src/csync/csync_exclude.h +++ b/src/csync/csync_exclude.h @@ -32,23 +32,21 @@ #include -enum csync_exclude_type_e { - CSYNC_NOT_EXCLUDED = 0, - CSYNC_FILE_SILENTLY_EXCLUDED, - CSYNC_FILE_EXCLUDE_AND_REMOVE, - CSYNC_FILE_EXCLUDE_LIST, - CSYNC_FILE_EXCLUDE_INVALID_CHAR, - CSYNC_FILE_EXCLUDE_TRAILING_SPACE, - CSYNC_FILE_EXCLUDE_LONG_FILENAME, - CSYNC_FILE_EXCLUDE_HIDDEN, - CSYNC_FILE_EXCLUDE_STAT_FAILED, - CSYNC_FILE_EXCLUDE_CONFLICT, - CSYNC_FILE_EXCLUDE_CANNOT_ENCODE, - CSYNC_FILE_EXCLUDE_SERVER_BLACKLISTED, +enum CSYNC_EXCLUDE_TYPE { + CSYNC_NOT_EXCLUDED = 0, + CSYNC_FILE_SILENTLY_EXCLUDED, + CSYNC_FILE_EXCLUDE_AND_REMOVE, // TODO: is there still a difference to CSYNC_FILE_SILENTLY_EXCLUDED + CSYNC_FILE_EXCLUDE_LIST, + CSYNC_FILE_EXCLUDE_INVALID_CHAR, + CSYNC_FILE_EXCLUDE_TRAILING_SPACE, + CSYNC_FILE_EXCLUDE_LONG_FILENAME, + CSYNC_FILE_EXCLUDE_HIDDEN, + CSYNC_FILE_EXCLUDE_STAT_FAILED, + CSYNC_FILE_EXCLUDE_CONFLICT, + CSYNC_FILE_EXCLUDE_CANNOT_ENCODE, + CSYNC_FILE_EXCLUDE_SERVER_BLACKLISTED, + CSYNC_FILE_EXCLUDE_RESERVED, }; -typedef enum csync_exclude_type_e CSYNC_EXCLUDE_TYPE; - -class ExcludedFilesTest; /** * Manages file/directory exclusion. diff --git a/src/gui/folder.cpp b/src/gui/folder.cpp index 00d3846a582..fe011b6f055 100644 --- a/src/gui/folder.cpp +++ b/src/gui/folder.cpp @@ -113,6 +113,9 @@ Folder::Folder(const FolderDefinition &definition, connect(ProgressDispatcher::instance(), &ProgressDispatcher::folderConflicts, this, &Folder::slotFolderConflicts); + connect(_engine.data(), &SyncEngine::excluded, this, [this](const QString &path, CSYNC_EXCLUDE_TYPE reason) { + Q_EMIT ProgressDispatcher::instance()->excluded(this, path, reason); + }); _localDiscoveryTracker.reset(new LocalDiscoveryTracker); connect(_engine.data(), &SyncEngine::finished, diff --git a/src/gui/issueswidget.cpp b/src/gui/issueswidget.cpp index 99d622d19b0..a5b9f2e2fb9 100644 --- a/src/gui/issueswidget.cpp +++ b/src/gui/issueswidget.cpp @@ -69,10 +69,23 @@ IssuesWidget::IssuesWidget(QWidget *parent) auto item = SyncFileItemPtr::create(); item->_status = SyncFileItem::NormalError; item->_errorString = message; - item->_responseTimeStamp = QDateTime::currentDateTime().toString(Qt::RFC2822Date).toUtf8(); _model->addProtocolItem(ProtocolItem { folderAlias, item }); }); + connect(ProgressDispatcher::instance(), &ProgressDispatcher::excluded, this, [this](Folder *f, const QString &file, CSYNC_EXCLUDE_TYPE reason) { + auto item = SyncFileItemPtr::create(); + item->_status = SyncFileItem::FileIgnored; + item->_file = file; + switch (reason) { + case CSYNC_FILE_EXCLUDE_RESERVED: + item->_errorString = tr("The file %1 was ignored as its name is reserved by %2").arg(file, Theme::instance()->appNameGUI()); + break; + default: + Q_UNREACHABLE(); + } + _model->addProtocolItem(ProtocolItem { f, item }); + }); + _model = new ProtocolItemModel(this); _sortModel = new QSortFilterProxyModel(this); _sortModel->setSourceModel(_model); @@ -126,7 +139,12 @@ void IssuesWidget::slotProgressInfo(const QString &folder, const ProgressInfo &p const auto &engine = f->syncEngine(); const auto style = engine.lastLocalDiscoveryStyle(); _model->remove_if([&](const ProtocolItem &item) { - if (item.folder()->path() != folder) { + if (item.folder() != f) { + return false; + } + if (item.direction() == SyncFileItem::None) { + // TODO: don't clear syncErrors and excludes for now. + // make them either unique or remove them on the next sync? return false; } if (style == LocalDiscoveryStyle::FilesystemOnly) { diff --git a/src/gui/protocolitem.cpp b/src/gui/protocolitem.cpp index cc7ed5c403e..2d46b3dac6e 100644 --- a/src/gui/protocolitem.cpp +++ b/src/gui/protocolitem.cpp @@ -24,9 +24,10 @@ using namespace OCC; -ProtocolItem::ProtocolItem(const QString &folder, const SyncFileItemPtr &item) + +ProtocolItem::ProtocolItem(Folder *folder, const SyncFileItemPtr &item) : _path(item->destination()) - , _folder(FolderMan::instance()->folder(folder)) + , _folder(folder) , _size(item->_size) , _status(item->_status) , _direction(item->_direction) @@ -43,6 +44,11 @@ ProtocolItem::ProtocolItem(const QString &folder, const SyncFileItemPtr &item) } } +ProtocolItem::ProtocolItem(const QString &folder, const SyncFileItemPtr &item) + : ProtocolItem(FolderMan::instance()->folder(folder), item) +{ +} + QString ProtocolItem::path() const { return _path; diff --git a/src/gui/protocolitem.h b/src/gui/protocolitem.h index 8f064a1aac9..144b5e38e4e 100644 --- a/src/gui/protocolitem.h +++ b/src/gui/protocolitem.h @@ -27,6 +27,7 @@ class ProtocolItem Q_GADGET public: ProtocolItem() = default; + explicit ProtocolItem(Folder *folder, const SyncFileItemPtr &item); explicit ProtocolItem(const QString &folder, const SyncFileItemPtr &item); QString path() const; diff --git a/src/libsync/discovery.cpp b/src/libsync/discovery.cpp index 787e0b26e2e..05f015159f3 100644 --- a/src/libsync/discovery.cpp +++ b/src/libsync/discovery.cpp @@ -219,6 +219,9 @@ bool ProcessDirectoryJob::handleExcluded(const QString &path, const QString &loc } else if (excluded == CSYNC_FILE_SILENTLY_EXCLUDED || excluded == CSYNC_FILE_EXCLUDE_AND_REMOVE) { emit _discoveryData->silentlyExcluded(path); return true; + } else if (excluded == CSYNC_FILE_EXCLUDE_RESERVED) { + emit _discoveryData->excluded(path, excluded); + return true; } auto item = SyncFileItemPtr::create(); @@ -234,6 +237,7 @@ bool ProcessDirectoryJob::handleExcluded(const QString &path, const QString &loc case CSYNC_NOT_EXCLUDED: case CSYNC_FILE_SILENTLY_EXCLUDED: case CSYNC_FILE_EXCLUDE_AND_REMOVE: + case CSYNC_FILE_EXCLUDE_RESERVED: qFatal("These were handled earlier"); case CSYNC_FILE_EXCLUDE_LIST: item->_errorString = tr("File is listed on the ignore list."); @@ -326,18 +330,6 @@ void ProcessDirectoryJob::processFile(PathTuple path, if (item->_type == ItemTypeVirtualFileDehydration) item->_type = ItemTypeFile; - // VFS suffixed files on the server are ignored - if (isVfsWithSuffix()) { - if (hasVirtualFileSuffix(serverEntry.name) - || (localEntry.isVirtualFile && !dbEntry.isVirtualFile() && hasVirtualFileSuffix(QString::fromUtf8(dbEntry._path)))) { - item->_instruction = CSYNC_INSTRUCTION_IGNORE; - item->_errorString = tr("File has extension reserved for virtual files."); - _childIgnored = true; - emit _discoveryData->itemDiscovered(item); - return; - } - } - if (serverEntry.isValid()) { processFileAnalyzeRemoteInfo(item, path, localEntry, serverEntry, dbEntry); return; diff --git a/src/libsync/discoveryphase.cpp b/src/libsync/discoveryphase.cpp index 0488c9f8c49..0fc34df6ba5 100644 --- a/src/libsync/discoveryphase.cpp +++ b/src/libsync/discoveryphase.cpp @@ -38,8 +38,6 @@ Q_LOGGING_CATEGORY(lcDiscovery, "sync.discovery", QtInfoMsg) /* Given a sorted list of paths ending with '/', return whether or not the given path is within one of the paths of the list*/ static bool findPathInList(const QStringList &list, const QString &path) { - Q_ASSERT(std::is_sorted(list.begin(), list.end())); - if (list.size() == 1 && list.first() == QLatin1String("/")) { // Special case for the case "/" is there, it matches everything return true; diff --git a/src/libsync/discoveryphase.h b/src/libsync/discoveryphase.h index 579d8ff252c..e12fc6a0253 100644 --- a/src/libsync/discoveryphase.h +++ b/src/libsync/discoveryphase.h @@ -28,7 +28,7 @@ #include "syncoptions.h" #include "syncfileitem.h" -class ExcludedFiles; +#include "csync/csync_exclude.h" namespace OCC { @@ -270,6 +270,7 @@ class DiscoveryPhase : public QObject * The path is relative to the sync folder, similar to item->_file */ void silentlyExcluded(const QString &folderPath); + void excluded(const QString &folderPath, CSYNC_EXCLUDE_TYPE reason); }; /// Implementation of DiscoveryPhase::adjustRenamedPath diff --git a/src/libsync/owncloudpropagator.cpp b/src/libsync/owncloudpropagator.cpp index 7f6d86d55df..daa8d5f067c 100644 --- a/src/libsync/owncloudpropagator.cpp +++ b/src/libsync/owncloudpropagator.cpp @@ -369,10 +369,8 @@ qint64 OwncloudPropagator::smallFileSize() return smallFileSize; } -void OwncloudPropagator::start(SyncFileItemVector &&items) +void OwncloudPropagator::start(SyncFileItemSet &&items) { - Q_ASSERT(std::is_sorted(items.begin(), items.end())); - /* This builds all the jobs needed for the propagation. * Each directory is a PropagateDirectory job, which contains the files in it. * In order to do that we loop over the items. (which are sorted by destination) @@ -833,9 +831,9 @@ bool PropagatorCompositeJob::scheduleSelfOrChild() // Now it's our turn, check if we have something left to do. // First, convert a task to a job if necessary - while (_jobsToDo.isEmpty() && !_tasksToDo.isEmpty()) { - SyncFileItemPtr nextTask = _tasksToDo.first(); - _tasksToDo.remove(0); + while (_jobsToDo.empty() && !_tasksToDo.empty()) { + const SyncFileItemPtr nextTask = *_tasksToDo.begin(); + _tasksToDo.erase(_tasksToDo.begin()); PropagatorJob *job = propagator()->createJob(nextTask); if (!job) { qCWarning(lcDirectory) << "Useless task found for file" << nextTask->destination() << "instruction" << nextTask->_instruction; @@ -854,7 +852,7 @@ bool PropagatorCompositeJob::scheduleSelfOrChild() // If neither us or our children had stuff left to do we could hang. Make sure // we mark this job as finished so that the propagator can schedule a new one. - if (_jobsToDo.isEmpty() && _tasksToDo.isEmpty() && _runningJobs.isEmpty()) { + if (_jobsToDo.isEmpty() && _tasksToDo.empty() && _runningJobs.isEmpty()) { // Our parent jobs are already iterating over their running jobs, post to the event loop // to avoid removing ourself from that list while they iterate. QMetaObject::invokeMethod(this, "finalize", Qt::QueuedConnection); @@ -883,7 +881,7 @@ void PropagatorCompositeJob::slotSubJobFinished(SyncFileItem::Status status) _hasError = status; } - if (_jobsToDo.isEmpty() && _tasksToDo.isEmpty() && _runningJobs.isEmpty()) { + if (_jobsToDo.isEmpty() && _tasksToDo.empty() && _runningJobs.isEmpty()) { finalize(); } else { propagator()->scheduleNextJob(); diff --git a/src/libsync/owncloudpropagator.h b/src/libsync/owncloudpropagator.h index 68ea1ae55bd..c22ab9e90f5 100644 --- a/src/libsync/owncloudpropagator.h +++ b/src/libsync/owncloudpropagator.h @@ -212,7 +212,7 @@ class PropagatorCompositeJob : public PropagatorJob Q_OBJECT public: QVector _jobsToDo; - SyncFileItemVector _tasksToDo; + SyncFileItemSet _tasksToDo; QVector _runningJobs; SyncFileItem::Status _hasError; // NoStatus, or NormalError / SoftError if there was an error quint64 _abortsCount; @@ -233,7 +233,7 @@ class PropagatorCompositeJob : public PropagatorJob void appendJob(PropagatorJob *job); void appendTask(const SyncFileItemPtr &item) { - _tasksToDo.append(item); + _tasksToDo.insert(item); } bool scheduleSelfOrChild() override; @@ -412,7 +412,7 @@ class OWNCLOUDSYNC_EXPORT OwncloudPropagator : public QObject ~OwncloudPropagator() override; - void start(SyncFileItemVector &&_syncedItems); + void start(SyncFileItemSet &&_syncedItems); const SyncOptions &syncOptions() const; void setSyncOptions(const SyncOptions &syncOptions); diff --git a/src/libsync/progressdispatcher.h b/src/libsync/progressdispatcher.h index a5ed53624af..fdcc16883fa 100644 --- a/src/libsync/progressdispatcher.h +++ b/src/libsync/progressdispatcher.h @@ -25,8 +25,10 @@ #include "syncfileitem.h" -namespace OCC { +#include "csync/csync_exclude.h" +namespace OCC { +class Folder; /** * @brief The ProgressInfo class * @ingroup libsync @@ -311,6 +313,9 @@ class OWNCLOUDSYNC_EXPORT ProgressDispatcher : public QObject */ void syncError(const QString &folder, const QString &message, ErrorCategory category); + void excluded(Folder *folder, const QString &path, CSYNC_EXCLUDE_TYPE reason); + + /** * @brief Emitted for a folder when a sync is done, listing all pending conflicts */ diff --git a/src/libsync/syncengine.cpp b/src/libsync/syncengine.cpp index ba98adce621..f9566783d93 100644 --- a/src/libsync/syncengine.cpp +++ b/src/libsync/syncengine.cpp @@ -95,7 +95,7 @@ SyncEngine::SyncEngine(AccountPtr account, const QString &localPath, qRegisterMetaType("SyncFileItemPtr"); qRegisterMetaType("SyncFileItem::Status"); qRegisterMetaType("SyncFileStatus"); - qRegisterMetaType("SyncFileItemVector"); + qRegisterMetaType("SyncFileItemSet"); qRegisterMetaType("SyncFileItem::Direction"); // Everything in the SyncEngine expects a trailing slash for the localPath. @@ -198,7 +198,7 @@ static bool isFileTransferInstruction(SyncInstructions instruction) || instruction == CSYNC_INSTRUCTION_TYPE_CHANGE; } -void SyncEngine::deleteStaleDownloadInfos(const SyncFileItemVector &syncItems) +void SyncEngine::deleteStaleDownloadInfos(const SyncFileItemSet &syncItems) { // Find all downloadinfo paths that we want to preserve. QSet download_file_paths; @@ -220,7 +220,7 @@ void SyncEngine::deleteStaleDownloadInfos(const SyncFileItemVector &syncItems) } } -void SyncEngine::deleteStaleUploadInfos(const SyncFileItemVector &syncItems) +void SyncEngine::deleteStaleUploadInfos(const SyncFileItemSet &syncItems) { // Find all blacklisted paths that we want to preserve. QSet upload_file_paths; @@ -246,7 +246,7 @@ void SyncEngine::deleteStaleUploadInfos(const SyncFileItemVector &syncItems) } } -void SyncEngine::deleteStaleErrorBlacklistEntries(const SyncFileItemVector &syncItems) +void SyncEngine::deleteStaleErrorBlacklistEntries(const SyncFileItemSet &syncItems) { // Find all blacklisted paths that we want to preserve. QSet blacklist_file_paths; @@ -396,9 +396,16 @@ void OCC::SyncEngine::slotItemDiscovered(const OCC::SyncFileItemPtr &item) checkErrorBlacklisting(*item); _needsUpdate = true; - // Insert sorted - auto it = std::lower_bound( _syncItems.begin(), _syncItems.end(), item ); // the _syncItems is sorted - _syncItems.insert( it, item ); + Q_ASSERT([&] { + const auto it = _syncItems.find(item); + if (it != _syncItems.cend()) { + const auto &item2 = it->get(); + qCWarning(lcEngine) << "We already have an item for " << item2->_file << ":" << item2->_instruction << item2->_direction << "|" << item->_instruction << item->_direction; + return false; + } + return true; + }()); + _syncItems.insert(item); slotNewItem(item); @@ -557,6 +564,10 @@ void SyncEngine::startSync() connect(_discoveryPhase.data(), &DiscoveryPhase::finished, this, &SyncEngine::slotDiscoveryFinished); connect(_discoveryPhase.data(), &DiscoveryPhase::silentlyExcluded, _syncFileStatusTracker.data(), &SyncFileStatusTracker::slotAddSilentlyExcluded); + connect(_discoveryPhase.data(), &DiscoveryPhase::excluded, + _syncFileStatusTracker.data(), &SyncFileStatusTracker::slotAddSilentlyExcluded); + connect(_discoveryPhase.data(), &DiscoveryPhase::excluded, + this, &SyncEngine::excluded); auto discoveryJob = new ProcessDirectoryJob( _discoveryPhase.data(), PinState::AlwaysLocal, _discoveryPhase.data()); @@ -657,10 +668,22 @@ void SyncEngine::slotDiscoveryFinished() } while (index > 0); } } - _syncItems.erase(std::remove_if(_syncItems.begin(), _syncItems.end(), [&names](auto i) { + //std::erase_if c++20 + // https://en.cppreference.com/w/cpp/container/set/erase_if + const auto erase_if = [](auto &c, const auto &pred) { + auto old_size = c.size(); + for (auto i = c.begin(), last = c.end(); i != last;) { + if (pred(*i)) { + i = c.erase(i); + } else { + ++i; + } + } + return old_size - c.size(); + }; + erase_if(_syncItems, [&names](const SyncFileItemPtr &i) { return !names.contains(QStringRef { &i->_file }); - }), - _syncItems.end()); + }); } qCInfo(lcEngine) << "#### Reconcile (aboutToPropagate) #################################################### " << _stopWatch.addLapTime(QStringLiteral("Reconcile (aboutToPropagate)")) << "ms"; @@ -838,7 +861,7 @@ void SyncEngine::updateFileTotal(const SyncFileItem &item, qint64 newSize) _progressInfo->updateTotalsForFile(item, newSize); emit transmissionProgress(*_progressInfo); } -void SyncEngine::restoreOldFiles(SyncFileItemVector &syncItems) +void SyncEngine::restoreOldFiles(SyncFileItemSet &syncItems) { /* When the server is trying to send us lots of file in the past, this means that a backup was restored in the server. In that case, we should not simply overwrite the newer file diff --git a/src/libsync/syncengine.h b/src/libsync/syncengine.h index f8794d9bff5..4ffa0477724 100644 --- a/src/libsync/syncengine.h +++ b/src/libsync/syncengine.h @@ -26,6 +26,8 @@ #include #include +#include "csync/csync_exclude.h" + #include "syncfileitem.h" #include "progressdispatcher.h" #include "common/utility.h" @@ -141,7 +143,7 @@ class OWNCLOUDSYNC_EXPORT SyncEngine : public QObject void rootEtag(const QByteArray &, const QDateTime &); // after the above signals. with the items that actually need propagating - void aboutToPropagate(SyncFileItemVector &); + void aboutToPropagate(SyncFileItemSet &); // after each item completed by a job (successful or not) void itemCompleted(const SyncFileItemPtr &); @@ -150,6 +152,7 @@ class OWNCLOUDSYNC_EXPORT SyncEngine : public QObject /// We've produced a new sync error of a type. void syncError(const QString &message, ErrorCategory category = ErrorCategory::Normal); + void excluded(const QString &path, CSYNC_EXCLUDE_TYPE reason); void finished(bool success); void started(); @@ -208,13 +211,13 @@ private slots: // Cleans up unnecessary downloadinfo entries in the journal as well // as their temporary files. - void deleteStaleDownloadInfos(const SyncFileItemVector &syncItems); + void deleteStaleDownloadInfos(const SyncFileItemSet &syncItems); // Removes stale uploadinfos from the journal. - void deleteStaleUploadInfos(const SyncFileItemVector &syncItems); + void deleteStaleUploadInfos(const SyncFileItemSet &syncItems); // Removes stale error blacklist entries from the journal. - void deleteStaleErrorBlacklistEntries(const SyncFileItemVector &syncItems); + void deleteStaleErrorBlacklistEntries(const SyncFileItemSet &syncItems); // Removes stale and adds missing conflict records after sync void conflictRecordMaintenance(); @@ -223,7 +226,7 @@ private slots: void finalize(bool success); // Must only be acessed during update and reconcile - QVector _syncItems; + SyncFileItemSet _syncItems; AccountPtr _account; bool _needsUpdate; @@ -248,13 +251,13 @@ private slots: * check if we are allowed to propagate everything, and if we are not, adjust the instructions * to recover */ - void checkForPermission(SyncFileItemVector &syncItems); + void checkForPermission(SyncFileItemSet &syncItems); RemotePermissions getPermissions(const QString &file) const; /** * Instead of downloading files from the server, upload the files to the server */ - void restoreOldFiles(SyncFileItemVector &syncItems); + void restoreOldFiles(SyncFileItemSet &syncItems); // true if there is at least one file which was not changed on the server bool _hasNoneFiles; diff --git a/src/libsync/syncfileitem.h b/src/libsync/syncfileitem.h index d927befbb76..a43960bd810 100644 --- a/src/libsync/syncfileitem.h +++ b/src/libsync/syncfileitem.h @@ -21,6 +21,8 @@ #include #include +#include + #include #include @@ -281,7 +283,7 @@ inline bool operator<(const SyncFileItemPtr &item1, const SyncFileItemPtr &item2 return *item1 < *item2; } -typedef QVector SyncFileItemVector; +using SyncFileItemSet = std::set; } Q_DECLARE_METATYPE(OCC::SyncFileItem) diff --git a/src/libsync/syncfilestatustracker.cpp b/src/libsync/syncfilestatustracker.cpp index 84071f28493..583aadd0a7f 100644 --- a/src/libsync/syncfilestatustracker.cpp +++ b/src/libsync/syncfilestatustracker.cpp @@ -204,7 +204,7 @@ void SyncFileStatusTracker::decSyncCountAndEmitStatusChanged(const QString &rela } } -void SyncFileStatusTracker::slotAboutToPropagate(SyncFileItemVector &items) +void SyncFileStatusTracker::slotAboutToPropagate(SyncFileItemSet &items) { OC_ASSERT(_syncCount.isEmpty()); diff --git a/src/libsync/syncfilestatustracker.h b/src/libsync/syncfilestatustracker.h index 8396cfd651c..7a89bab23e5 100644 --- a/src/libsync/syncfilestatustracker.h +++ b/src/libsync/syncfilestatustracker.h @@ -47,7 +47,7 @@ public slots: void fileStatusChanged(const QString &systemFileName, SyncFileStatus fileStatus); private slots: - void slotAboutToPropagate(SyncFileItemVector &items); + void slotAboutToPropagate(SyncFileItemSet &items); void slotItemCompleted(const SyncFileItemPtr &item); void slotSyncFinished(); void slotSyncEngineRunningChanged(); diff --git a/src/libsync/syncresult.h b/src/libsync/syncresult.h index af396c3396d..179324c6150 100644 --- a/src/libsync/syncresult.h +++ b/src/libsync/syncresult.h @@ -85,7 +85,7 @@ class OWNCLOUDSYNC_EXPORT SyncResult private: Status _status; - SyncFileItemVector _syncItems; + SyncFileItemSet _syncItems; QDateTime _syncTime; QString _folder; /** diff --git a/test/testchunkingng.cpp b/test/testchunkingng.cpp index 401a21c1394..fc9896dfbfb 100644 --- a/test/testchunkingng.cpp +++ b/test/testchunkingng.cpp @@ -268,9 +268,9 @@ private slots: // Now the next sync gets a NEW/NEW conflict and since there's no checksum // it just becomes a UPDATE_METADATA - auto checkEtagUpdated = [&](SyncFileItemVector &items) { + auto checkEtagUpdated = [&](SyncFileItemSet &items) { QCOMPARE(items.size(), 1); - QCOMPARE(items[0]->_file, QLatin1String("A")); + QCOMPARE(items.begin()->get()->_file, QLatin1String("A")); SyncJournalFileRecord record; QVERIFY(fakeFolder.syncJournal().getFileRecord(QByteArray("A/a0"), &record)); QCOMPARE(record._etag, fakeFolder.remoteModifier().find("A/a0")->etag); diff --git a/test/testpermissions.cpp b/test/testpermissions.cpp index 012c91a71d2..f95ce1e4dc4 100644 --- a/test/testpermissions.cpp +++ b/test/testpermissions.cpp @@ -41,7 +41,7 @@ static void assertCsyncJournalOk(SyncJournalDb &journal) #endif } -SyncFileItemPtr findDiscoveryItem(const SyncFileItemVector &spy, const QString &path) +SyncFileItemPtr findDiscoveryItem(const SyncFileItemSet &spy, const QString &path) { for (const auto &item : spy) { if (item->destination() == path) @@ -53,10 +53,11 @@ SyncFileItemPtr findDiscoveryItem(const SyncFileItemVector &spy, const QString & bool itemInstruction(const ItemCompletedSpy &spy, const QString &path, const SyncInstructions instr) { auto item = spy.findItem(path); + Q_ASSERT(!item.isNull()); return item->_instruction == instr; } -bool discoveryInstruction(const SyncFileItemVector &spy, const QString &path, const SyncInstructions instr) +bool discoveryInstruction(const SyncFileItemSet &spy, const QString &path, const SyncInstructions instr) { auto item = findDiscoveryItem(spy, path); return item->_instruction == instr; @@ -406,14 +407,14 @@ private slots: lm.rename("zallowed/sub2", "nocreatedir/zsub2"); // also hook into discovery!! - SyncFileItemVector discovery; + SyncFileItemSet discovery; connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToPropagate, this, [&discovery](auto v) { discovery = v; }); ItemCompletedSpy completeSpy(fakeFolder); QVERIFY(!fakeFolder.syncOnce()); // if renaming doesn't work, just delete+create QVERIFY(itemInstruction(completeSpy, "norename/file", CSYNC_INSTRUCTION_REMOVE)); - QVERIFY(itemInstruction(completeSpy, "norename/sub", CSYNC_INSTRUCTION_NONE)); + QVERIFY(completeSpy.findItem("norename/sub").isNull()); QVERIFY(discoveryInstruction(discovery, "norename/sub", CSYNC_INSTRUCTION_REMOVE)); QVERIFY(itemInstruction(completeSpy, "norename/file_renamed", CSYNC_INSTRUCTION_NEW)); QVERIFY(itemInstruction(completeSpy, "norename/sub_renamed", CSYNC_INSTRUCTION_NEW)); @@ -422,7 +423,7 @@ private slots: // simiilarly forbidding moves becomes delete+create QVERIFY(itemInstruction(completeSpy, "nomove/file", CSYNC_INSTRUCTION_REMOVE)); - QVERIFY(itemInstruction(completeSpy, "nomove/sub", CSYNC_INSTRUCTION_NONE)); + QVERIFY(completeSpy.findItem("norename/sub").isNull()); QVERIFY(discoveryInstruction(discovery, "nomove/sub", CSYNC_INSTRUCTION_REMOVE)); // nomove/sub/file is removed as part of the dir QVERIFY(itemInstruction(completeSpy, "allowed/file_moved", CSYNC_INSTRUCTION_NEW)); @@ -438,8 +439,8 @@ private slots: // and the sources of the invalid moves should be restored, not deleted // (depending on the order of discovery a follow-up sync is needed) - QVERIFY(itemInstruction(completeSpy, "allowed/file", CSYNC_INSTRUCTION_NONE)); - QVERIFY(itemInstruction(completeSpy, "allowed/sub2", CSYNC_INSTRUCTION_NONE)); + QVERIFY(completeSpy.findItem("allowed/file").isNull()); + QVERIFY(completeSpy.findItem("allowed/sub2").isNull()); QVERIFY(itemInstruction(completeSpy, "zallowed/file", CSYNC_INSTRUCTION_NEW)); QVERIFY(itemInstruction(completeSpy, "zallowed/sub2", CSYNC_INSTRUCTION_NEW)); QVERIFY(itemInstruction(completeSpy, "zallowed/sub2/file", CSYNC_INSTRUCTION_NEW)); diff --git a/test/testsyncengine.cpp b/test/testsyncengine.cpp index 89fe334204d..07c307c7c31 100644 --- a/test/testsyncengine.cpp +++ b/test/testsyncengine.cpp @@ -400,7 +400,7 @@ private slots: fakeFolder.remoteModifier().appendByte("C/c1"); fakeFolder.remoteModifier().setModTime("C/c1", changedMtime2); - connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToPropagate, [&](SyncFileItemVector &items) { + connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToPropagate, [&](SyncFileItemSet &items) { SyncFileItemPtr a1, b1, c1; for (auto &item : items) { if (item->_file == "A/a1") diff --git a/test/testsyncvirtualfiles.cpp b/test/testsyncvirtualfiles.cpp index 0da42b288d1..a55748c9fc3 100644 --- a/test/testsyncvirtualfiles.cpp +++ b/test/testsyncvirtualfiles.cpp @@ -18,6 +18,7 @@ using namespace OCC; auto itemInstruction(const ItemCompletedSpy &spy, const QString &path) { auto item = spy.findItem(path); + Q_ASSERT(!item.isNull()); return item->_instruction; } @@ -375,10 +376,8 @@ private slots: QVERIFY(fakeFolder.syncOnce()); QCOMPARE(itemInstruction(completeSpy, "A/a1"), CSYNC_INSTRUCTION_SYNC); QCOMPARE(completeSpy.findItem("A/a1")->_type, ItemTypeVirtualFileDownload); - QCOMPARE(itemInstruction(completeSpy, "A/a1" DVSUFFIX), CSYNC_INSTRUCTION_NONE); QCOMPARE(itemInstruction(completeSpy, "A/a2"), CSYNC_INSTRUCTION_SYNC); QCOMPARE(completeSpy.findItem("A/a2")->_type, ItemTypeVirtualFileDownload); - QCOMPARE(itemInstruction(completeSpy, "A/a2" DVSUFFIX), CSYNC_INSTRUCTION_NONE); QCOMPARE(itemInstruction(completeSpy, "A/a3" DVSUFFIX), CSYNC_INSTRUCTION_REMOVE); QCOMPARE(itemInstruction(completeSpy, "A/a4m"), CSYNC_INSTRUCTION_NEW); QCOMPARE(itemInstruction(completeSpy, "A/a4" DVSUFFIX), CSYNC_INSTRUCTION_REMOVE); @@ -447,7 +446,6 @@ private slots: fakeFolder.serverErrorPaths().append("A/a1", 500); QVERIFY(!fakeFolder.syncOnce()); QCOMPARE(itemInstruction(completeSpy, "A/a1"), CSYNC_INSTRUCTION_SYNC); - QCOMPARE(itemInstruction(completeSpy, "A/a1" DVSUFFIX), CSYNC_INSTRUCTION_NONE); QVERIFY(fakeFolder.currentLocalState().find("A/a1" DVSUFFIX)); QVERIFY(!fakeFolder.currentLocalState().find("A/a1")); QCOMPARE(dbRecord(fakeFolder, "A/a1" DVSUFFIX)._type, ItemTypeVirtualFileDownload); @@ -457,7 +455,6 @@ private slots: fakeFolder.serverErrorPaths().clear(); QVERIFY(fakeFolder.syncOnce()); QCOMPARE(itemInstruction(completeSpy, "A/a1"), CSYNC_INSTRUCTION_SYNC); - QCOMPARE(itemInstruction(completeSpy, "A/a1" DVSUFFIX), CSYNC_INSTRUCTION_NONE); QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); QCOMPARE(dbRecord(fakeFolder, "A/a1")._type, ItemTypeFile); QVERIFY(!dbRecord(fakeFolder, "A/a1" DVSUFFIX).isValid()); @@ -897,8 +894,8 @@ private slots: fakeFolder.switchToVfs(QSharedPointer(new VfsOff)); QVERIFY(fakeFolder.syncOnce()); - QVERIFY(fakeFolder.currentRemoteState().find("A/a3" DVSUFFIX)); // regular upload - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + QVERIFY(!fakeFolder.currentRemoteState().find("A/a3" DVSUFFIX)); // regular upload + QVERIFY(fakeFolder.currentLocalState() != fakeFolder.currentRemoteState()); } void testNewVirtuals() @@ -978,128 +975,6 @@ private slots: QVERIFY(fakeFolder.currentLocalState().find("unspec/file1" DVSUFFIX)); } - // Check what happens if vfs-suffixed files exist on the server or locally - // while the file is hydrated - void testSuffixFilesWhileLocalHydrated() - { - FakeFolder fakeFolder{ FileInfo() }; - - ItemCompletedSpy completeSpy(fakeFolder); - auto cleanup = [&]() { - completeSpy.clear(); - }; - cleanup(); - - // suffixed files are happily synced with Vfs::Off - fakeFolder.remoteModifier().mkdir("A"); - fakeFolder.remoteModifier().insert("A/test1" DVSUFFIX, 10, 'A'); - fakeFolder.remoteModifier().insert("A/test2" DVSUFFIX, 20, 'A'); - fakeFolder.remoteModifier().insert("A/file1" DVSUFFIX, 30, 'A'); - fakeFolder.remoteModifier().insert("A/file2", 40, 'A'); - fakeFolder.remoteModifier().insert("A/file2" DVSUFFIX, 50, 'A'); - fakeFolder.remoteModifier().insert("A/file3", 60, 'A'); - fakeFolder.remoteModifier().insert("A/file3" DVSUFFIX, 70, 'A'); - fakeFolder.remoteModifier().insert("A/file3" DVSUFFIX DVSUFFIX, 80, 'A'); - fakeFolder.remoteModifier().insert("A/remote1" DVSUFFIX, 30, 'A'); - fakeFolder.remoteModifier().insert("A/remote2", 40, 'A'); - fakeFolder.remoteModifier().insert("A/remote2" DVSUFFIX, 50, 'A'); - fakeFolder.remoteModifier().insert("A/remote3", 60, 'A'); - fakeFolder.remoteModifier().insert("A/remote3" DVSUFFIX, 70, 'A'); - fakeFolder.remoteModifier().insert("A/remote3" DVSUFFIX DVSUFFIX, 80, 'A'); - QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); - cleanup(); - - // Enable suffix vfs - setupVfs(fakeFolder); - - // A simple sync removes the files that are now ignored (?) - QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(itemInstruction(completeSpy, "A/file1" DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - QCOMPARE(itemInstruction(completeSpy, "A/file2" DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - QCOMPARE(itemInstruction(completeSpy, "A/file3" DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - QCOMPARE(itemInstruction(completeSpy, "A/file3" DVSUFFIX DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - cleanup(); - - // Add a real file where the suffixed file exists - fakeFolder.localModifier().insert("A/test1", 11, 'A'); - fakeFolder.remoteModifier().insert("A/test2", 21, 'A'); - QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(itemInstruction(completeSpy, "A/test1"), CSYNC_INSTRUCTION_NEW); - // this isn't fully good since some code requires size == 1 for placeholders - // (when renaming placeholder to real file). But the alternative would mean - // special casing this to allow CONFLICT at virtual file creation level. Ew. - QCOMPARE(itemInstruction(completeSpy, "A/test2" DVSUFFIX), CSYNC_INSTRUCTION_UPDATE_METADATA); - cleanup(); - - // Local changes of suffixed file do nothing - fakeFolder.localModifier().setContents("A/file1" DVSUFFIX, 'B'); - fakeFolder.localModifier().setContents("A/file2" DVSUFFIX, 'B'); - fakeFolder.localModifier().setContents("A/file3" DVSUFFIX, 'B'); - fakeFolder.localModifier().setContents("A/file3" DVSUFFIX DVSUFFIX, 'B'); - QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(itemInstruction(completeSpy, "A/file1" DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - QCOMPARE(itemInstruction(completeSpy, "A/file2" DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - QCOMPARE(itemInstruction(completeSpy, "A/file3" DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - QCOMPARE(itemInstruction(completeSpy, "A/file3" DVSUFFIX DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - cleanup(); - - // Remote changes don't do anything either - fakeFolder.remoteModifier().setContents("A/file1" DVSUFFIX, 'C'); - fakeFolder.remoteModifier().setContents("A/file2" DVSUFFIX, 'C'); - fakeFolder.remoteModifier().setContents("A/file3" DVSUFFIX, 'C'); - fakeFolder.remoteModifier().setContents("A/file3" DVSUFFIX DVSUFFIX, 'C'); - QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(itemInstruction(completeSpy, "A/file1" DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - QCOMPARE(itemInstruction(completeSpy, "A/file2" DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - QCOMPARE(itemInstruction(completeSpy, "A/file3" DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - QCOMPARE(itemInstruction(completeSpy, "A/file3" DVSUFFIX DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - cleanup(); - - // Local removal: when not querying server - fakeFolder.localModifier().remove("A/file1" DVSUFFIX); - fakeFolder.localModifier().remove("A/file2" DVSUFFIX); - fakeFolder.localModifier().remove("A/file3" DVSUFFIX); - fakeFolder.localModifier().remove("A/file3" DVSUFFIX DVSUFFIX); - QVERIFY(fakeFolder.syncOnce()); - QVERIFY(completeSpy.findItem("A/file1" DVSUFFIX)->isEmpty()); - QVERIFY(completeSpy.findItem("A/file2" DVSUFFIX)->isEmpty()); - QVERIFY(completeSpy.findItem("A/file3" DVSUFFIX)->isEmpty()); - QVERIFY(completeSpy.findItem("A/file3" DVSUFFIX DVSUFFIX)->isEmpty()); - cleanup(); - - // Local removal: when querying server - fakeFolder.remoteModifier().setContents("A/file1" DVSUFFIX, 'D'); - QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(itemInstruction(completeSpy, "A/file1" DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - QCOMPARE(itemInstruction(completeSpy, "A/file2" DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - QCOMPARE(itemInstruction(completeSpy, "A/file3" DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - QCOMPARE(itemInstruction(completeSpy, "A/file3" DVSUFFIX DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - cleanup(); - - // Remote removal - fakeFolder.remoteModifier().remove("A/remote1" DVSUFFIX); - fakeFolder.remoteModifier().remove("A/remote2" DVSUFFIX); - fakeFolder.remoteModifier().remove("A/remote3" DVSUFFIX); - fakeFolder.remoteModifier().remove("A/remote3" DVSUFFIX DVSUFFIX); - QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(itemInstruction(completeSpy, "A/remote1" DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - QCOMPARE(itemInstruction(completeSpy, "A/remote2" DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - QCOMPARE(itemInstruction(completeSpy, "A/remote3" DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - QCOMPARE(itemInstruction(completeSpy, "A/remote3" DVSUFFIX DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - cleanup(); - - // New files with a suffix aren't propagated downwards in the first place - fakeFolder.remoteModifier().insert("A/new1" DVSUFFIX); - QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(itemInstruction(completeSpy, "A/new1" DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - QVERIFY(fakeFolder.currentRemoteState().find("A/new1" DVSUFFIX)); - QVERIFY(!fakeFolder.currentLocalState().find("A/new1")); - QVERIFY(!fakeFolder.currentLocalState().find("A/new1" DVSUFFIX)); - QVERIFY(!fakeFolder.currentLocalState().find("A/new1" DVSUFFIX DVSUFFIX)); - cleanup(); - } - // Check what happens if vfs-suffixed files exist on the server or in the db void testExtraFilesLocalDehydrated() { @@ -1136,9 +1011,7 @@ private slots: QVERIFY(!fakeFolder.currentLocalState().find("A/file4" DVSUFFIX DVSUFFIX)); QCOMPARE(itemInstruction(completeSpy, "A/file1" DVSUFFIX), CSYNC_INSTRUCTION_NEW); QCOMPARE(itemInstruction(completeSpy, "A/file2" DVSUFFIX), CSYNC_INSTRUCTION_NEW); - QCOMPARE(itemInstruction(completeSpy, "A/file3" DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - QCOMPARE(itemInstruction(completeSpy, "A/file4" DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - QCOMPARE(itemInstruction(completeSpy, "A/file4" DVSUFFIX DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); + QCOMPARE(itemInstruction(completeSpy, "A/file3" DVSUFFIX), CSYNC_INSTRUCTION_NEW); cleanup(); // Create odd extra files locally and remotely @@ -1150,10 +1023,7 @@ private slots: QVERIFY(fakeFolder.syncOnce()); QCOMPARE(itemInstruction(completeSpy, "A/file1"), CSYNC_INSTRUCTION_CONFLICT); QCOMPARE(itemInstruction(completeSpy, "A/file1" DVSUFFIX), CSYNC_INSTRUCTION_REMOVE); // it's now a pointless real virtual file - QCOMPARE(itemInstruction(completeSpy, "A/file2" DVSUFFIX DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - QCOMPARE(itemInstruction(completeSpy, "A/file5" DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); QCOMPARE(itemInstruction(completeSpy, "A/file6"), CSYNC_INSTRUCTION_CONFLICT); - QCOMPARE(itemInstruction(completeSpy, "A/file6" DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); cleanup(); } @@ -1343,63 +1213,6 @@ private slots: QVERIFY(fakeFolder.currentLocalState().find("online/file1")); QVERIFY(fakeFolder.currentLocalState().find("local/file1" DVSUFFIX)); } - - void testPlaceHolderExist() { - FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() }; - fakeFolder.remoteModifier().insert("A/a1" DVSUFFIX, 111); - fakeFolder.remoteModifier().insert("A/hello" DVSUFFIX, 222); - QVERIFY(fakeFolder.syncOnce()); - auto vfs = setupVfs(fakeFolder); - - ItemCompletedSpy completeSpy(fakeFolder); - auto cleanup = [&]() { completeSpy.clear(); }; - cleanup(); - - QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); - QCOMPARE(itemInstruction(completeSpy, "A/a1" DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - QCOMPARE(itemInstruction(completeSpy, "A/hello" DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - - fakeFolder.remoteModifier().insert("A/a2" DVSUFFIX); - fakeFolder.remoteModifier().insert("A/hello", 12); - fakeFolder.localModifier().insert("A/igno" DVSUFFIX, 123); - cleanup(); - QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(itemInstruction(completeSpy, "A/a1" DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - QCOMPARE(itemInstruction(completeSpy, "A/igno" DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - - // verify that the files are still present - QCOMPARE(fakeFolder.currentLocalState().find("A/hello" DVSUFFIX)->size, 222); - QCOMPARE(*fakeFolder.currentLocalState().find("A/hello" DVSUFFIX), - *fakeFolder.currentRemoteState().find("A/hello" DVSUFFIX)); - QCOMPARE(fakeFolder.currentLocalState().find("A/igno" DVSUFFIX)->size, 123); - - cleanup(); - // Dehydrate - vfs->setPinState(QString(), PinState::OnlineOnly); - QVERIFY(!fakeFolder.syncOnce()); - - QCOMPARE(itemInstruction(completeSpy, "A/igno" DVSUFFIX), CSYNC_INSTRUCTION_IGNORE); - // verify that the files are still present - QCOMPARE(fakeFolder.currentLocalState().find("A/a1" DVSUFFIX)->size, 111); - QCOMPARE(fakeFolder.currentLocalState().find("A/hello" DVSUFFIX)->size, 222); - QCOMPARE(*fakeFolder.currentLocalState().find("A/hello" DVSUFFIX), - *fakeFolder.currentRemoteState().find("A/hello" DVSUFFIX)); - QCOMPARE(*fakeFolder.currentLocalState().find("A/a1"), - *fakeFolder.currentRemoteState().find("A/a1")); - QCOMPARE(fakeFolder.currentLocalState().find("A/igno" DVSUFFIX)->size, 123); - - // Now disable vfs and check that all files are still there - cleanup(); - SyncEngine::wipeVirtualFiles(fakeFolder.localPath(), fakeFolder.syncJournal(), *vfs); - fakeFolder.switchToVfs(QSharedPointer(new VfsOff)); - QVERIFY(fakeFolder.syncOnce()); - QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); - QCOMPARE(fakeFolder.currentLocalState().find("A/a1" DVSUFFIX)->size, 111); - QCOMPARE(fakeFolder.currentLocalState().find("A/hello")->size, 12); - QCOMPARE(fakeFolder.currentLocalState().find("A/hello" DVSUFFIX)->size, 222); - QCOMPARE(fakeFolder.currentLocalState().find("A/igno" DVSUFFIX)->size, 123); - } }; QTEST_GUILESS_MAIN(TestSyncVirtualFiles) diff --git a/test/testutils/syncenginetestutils.cpp b/test/testutils/syncenginetestutils.cpp index c3422b13177..b31eb34e819 100644 --- a/test/testutils/syncenginetestutils.cpp +++ b/test/testutils/syncenginetestutils.cpp @@ -981,7 +981,7 @@ void FakeFolder::scheduleSync() void FakeFolder::execUntilBeforePropagation() { - QSignalSpy spy(_syncEngine.get(), SIGNAL(aboutToPropagate(SyncFileItemVector &))); + QSignalSpy spy(_syncEngine.get(), &OCC::SyncEngine::aboutToPropagate); QVERIFY(spy.wait()); } @@ -1086,7 +1086,7 @@ OCC::SyncFileItemPtr ItemCompletedSpy::findItem(const QString &path) const if (item->destination() == path) return item; } - return OCC::SyncFileItemPtr::create(); + return nullptr; } FakeReply::FakeReply(QObject *parent)