Просмотр исходного кода

Sync: Fix handling of virtual files in error state

Issue: #7799
Hannah von Reth 5 лет назад
Родитель
Сommit
85aefa4232
2 измененных файлов с 36 добавлено и 12 удалено
  1. 17 7
      src/libsync/discoveryphase.cpp
  2. 19 5
      test/testsyncmove.cpp

+ 17 - 7
src/libsync/discoveryphase.cpp

@@ -159,14 +159,24 @@ QPair<bool, QByteArray> DiscoveryPhase::findAndCancelDeletedJob(const QString &o
     QByteArray oldEtag;
     auto it = _deletedItem.find(originalPath);
     if (it != _deletedItem.end()) {
-        ENFORCE((*it)->_instruction == CSYNC_INSTRUCTION_REMOVE
+        const csync_instructions_e instruction = (*it)->_instruction;
+        if (instruction == CSYNC_INSTRUCTION_IGNORE && (*it)->_type == ItemTypeVirtualFile) {
             // re-creation of virtual files count as a delete
-             || ((*it)->_type == ItemTypeVirtualFile && (*it)->_instruction == CSYNC_INSTRUCTION_NEW)
-             || ((*it)->_isRestoration && (*it)->_instruction == CSYNC_INSTRUCTION_NEW)
-               );
-        (*it)->_instruction = CSYNC_INSTRUCTION_NONE;
-        result = true;
-        oldEtag = (*it)->_etag;
+            // a file might be in an error state and thus gets marked as CSYNC_INSTRUCTION_IGNORE
+            // after it was initially marked as CSYNC_INSTRUCTION_REMOVE
+            // return true, to not trigger any additional actions on that file that could elad to dataloss
+            result = true;
+            oldEtag = (*it)->_etag;
+        } else {
+            ENFORCE(instruction == CSYNC_INSTRUCTION_REMOVE
+                // re-creation of virtual files count as a delete
+                || ((*it)->_type == ItemTypeVirtualFile && instruction == CSYNC_INSTRUCTION_NEW)
+                || ((*it)->_isRestoration && instruction == CSYNC_INSTRUCTION_NEW)
+                );
+            (*it)->_instruction = CSYNC_INSTRUCTION_NONE;
+            result = true;
+            oldEtag = (*it)->_etag;
+        }
         _deletedItem.erase(it);
     }
     if (auto *otherJob = _queuedDeletedDirectories.take(originalPath)) {

+ 19 - 5
test/testsyncmove.cpp

@@ -880,7 +880,8 @@ private slots:
             }
             return s;
         };
-        const QByteArray testPath = "folder/folderA/file.txt";
+        const QString src = "folder/folderA/file.txt";
+        const QString dest = "folder/folderB/file.txt";
         FakeFolder fakeFolder{ FileInfo{ QString(), { FileInfo{ QStringLiteral("folder"), { FileInfo{ QStringLiteral("folderA"), { { QStringLiteral("file.txt"), 400 } } }, QStringLiteral("folderB") } } } } };
 
         QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
@@ -896,8 +897,13 @@ private slots:
             fakeFolder.syncOnce();
         }
 
-        fakeFolder.serverErrorPaths().append(testPath, 403);
-        fakeFolder.localModifier().rename(getName(testPath), getName("folder/folderB/file.txt"));
+
+        fakeFolder.serverErrorPaths().append(src, 403);
+        fakeFolder.localModifier().rename(getName(src), getName(dest));
+        QVERIFY(!fakeFolder.currentLocalState().find(getName(src)));
+        QVERIFY(fakeFolder.currentLocalState().find(getName(dest)));
+        QVERIFY(fakeFolder.currentRemoteState().find(src));
+        QVERIFY(!fakeFolder.currentRemoteState().find(dest));
 
         // sync1 file gets detected as error, instruction is still NEW_FILE
         fakeFolder.syncOnce();
@@ -910,8 +916,16 @@ private slots:
             fakeFolder.syncJournal().internalPinStates().setForPath("", PinState::AlwaysLocal);
             fakeFolder.syncOnce();
         }
-        // the sync must have failed as we have a file in the error state
-        QVERIFY(fakeFolder.currentLocalState() != fakeFolder.currentRemoteState());
+
+        QVERIFY(!fakeFolder.currentLocalState().find(src));
+        QVERIFY(fakeFolder.currentLocalState().find(getName(dest)));
+        if (vfsMode == Vfs::WithSuffix)
+        {
+            // the placeholder was not restored as it is still in error state
+            QVERIFY(!fakeFolder.currentLocalState().find(dest));
+        }
+        QVERIFY(fakeFolder.currentRemoteState().find(src));
+        QVERIFY(!fakeFolder.currentRemoteState().find(dest));
     }
 
 };