Merge pull request #6507 from nextcloud/backport/6503/stable-3.12

[stable-3.12] Bugfix. Exclude list. Fix stuck 'excluded' status in Windows Explorer after removing the exclude pattern.
This commit is contained in:
Matthieu Gallien 2024-03-05 13:42:30 +01:00 committed by GitHub
commit 479e1cb4e4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 62 additions and 0 deletions

View File

@ -450,6 +450,7 @@ void OCC::SyncEngine::slotItemDiscovered(const OCC::SyncFileItemPtr &item)
return;
} else if (item->_instruction == CSYNC_INSTRUCTION_NONE) {
_hasNoneFiles = true;
_syncFileStatusTracker->slotCheckAndRemoveSilentlyExcluded(item->_file);
if (_account->capabilities().uploadConflictFiles() && Utility::isConflictFile(item->_file)) {
// For uploaded conflict files, files with no action performed on them should
// be displayed: but we mustn't overwrite the instruction if something happens

View File

@ -172,9 +172,19 @@ void SyncFileStatusTracker::slotPathTouched(const QString &fileName)
void SyncFileStatusTracker::slotAddSilentlyExcluded(const QString &folderPath)
{
_syncProblems[folderPath] = SyncFileStatus::StatusExcluded;
_syncSilentExcludes[folderPath] = SyncFileStatus::StatusExcluded;
emit fileStatusChanged(getSystemDestination(folderPath), resolveSyncAndErrorStatus(folderPath, NotShared));
}
void SyncFileStatusTracker::slotCheckAndRemoveSilentlyExcluded(const QString &folderPath)
{
const auto foundIt = _syncSilentExcludes.find(folderPath);
if (foundIt != _syncSilentExcludes.end()) {
_syncSilentExcludes.erase(foundIt);
emit fileStatusChanged(getSystemDestination(folderPath), SyncFileStatus::StatusUpToDate);
}
}
void SyncFileStatusTracker::incSyncCountAndEmitStatusChanged(const QString &relativePath, SharedFlag sharedFlag)
{
// Will return 0 (and increase to 1) if the path wasn't in the map yet
@ -231,9 +241,11 @@ void SyncFileStatusTracker::slotAboutToPropagate(SyncFileItemVector &items)
if (hasErrorStatus(*item)) {
_syncProblems[item->destination()] = SyncFileStatus::StatusError;
_syncSilentExcludes.erase(item->destination());
invalidateParentPaths(item->destination());
} else if (hasExcludedStatus(*item)) {
_syncProblems[item->destination()] = SyncFileStatus::StatusExcluded;
_syncSilentExcludes.erase(item->destination());
}
SharedFlag sharedFlag = item->_remotePerm.hasPermission(RemotePermissions::IsShared) ? Shared : NotShared;
@ -281,6 +293,7 @@ void SyncFileStatusTracker::slotItemCompleted(const SyncFileItemPtr &item)
} else {
_syncProblems.erase(item->destination());
}
_syncSilentExcludes.erase(item->destination());
SharedFlag sharedFlag = item->_remotePerm.hasPermission(RemotePermissions::IsShared) ? Shared : NotShared;
if (item->_instruction != CSYNC_INSTRUCTION_NONE

View File

@ -42,6 +42,7 @@ public slots:
void slotPathTouched(const QString &fileName);
// path relative to folder
void slotAddSilentlyExcluded(const QString &folderPath);
void slotCheckAndRemoveSilentlyExcluded(const QString &folderPath);
signals:
void fileStatusChanged(const QString &systemFileName, OCC::SyncFileStatus fileStatus);
@ -74,6 +75,7 @@ private:
SyncEngine *_syncEngine;
ProblemsMap _syncProblems;
ProblemsMap _syncSilentExcludes;
QSet<QString> _dirtyPaths;
// Counts the number direct children currently being synced (has unfinished propagation jobs).
// We'll show a file/directory as SYNC as long as its sync count is > 0.

View File

@ -511,6 +511,52 @@ private slots:
statusSpy.clear();
}
void silentlyExcludedFilesRemovedFromExclude()
{
FakeFolder fakeFolder{{}};
fakeFolder.localModifier().mkdir("A");
fakeFolder.localModifier().mkdir("A/photos");
fakeFolder.localModifier().insert("A/photos/image.png");
fakeFolder.localModifier().insert("A/photos/image1.png");
fakeFolder.localModifier().insert("A/photos/image2.png");
StatusPushSpy statusSpy(fakeFolder.syncEngine());
fakeFolder.scheduleSync();
fakeFolder.execUntilFinished();
verifyThatPushMatchesPull(fakeFolder, statusSpy);
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
QCOMPARE(statusSpy.statusOf("A/photos/image.png"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
QCOMPARE(statusSpy.statusOf("A/photos/image1.png"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
QCOMPARE(statusSpy.statusOf("A/photos/image2.png"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
statusSpy.clear();
// add ignore pattern for .png files and Allow to Delete
fakeFolder.syncEngine().excludedFiles().addManualExclude(QStringLiteral("]*.png"));
// sync again and make sure .png files are ignored
fakeFolder.scheduleSync();
fakeFolder.execUntilFinished();
verifyThatPushMatchesPull(fakeFolder, statusSpy);
QCOMPARE(statusSpy.statusOf("A/photos/image.png"), SyncFileStatus(SyncFileStatus::StatusExcluded));
QCOMPARE(statusSpy.statusOf("A/photos/image1.png"), SyncFileStatus(SyncFileStatus::StatusExcluded));
QCOMPARE(statusSpy.statusOf("A/photos/image2.png"), SyncFileStatus(SyncFileStatus::StatusExcluded));
statusSpy.clear();
// remove exclude for .png files
fakeFolder.syncEngine().excludedFiles().clearManualExcludes();
fakeFolder.syncEngine().excludedFiles().reloadExcludeFiles();
// make sure the status is again correct
fakeFolder.scheduleSync();
fakeFolder.execUntilFinished();
verifyThatPushMatchesPull(fakeFolder, statusSpy);
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
QCOMPARE(statusSpy.statusOf("A/photos/image.png"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
QCOMPARE(statusSpy.statusOf("A/photos/image1.png"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
QCOMPARE(statusSpy.statusOf("A/photos/image2.png"), SyncFileStatus(SyncFileStatus::StatusUpToDate));
statusSpy.clear();
}
};
QTEST_GUILESS_MAIN(TestSyncFileStatusTracker)