SyncEngine: _hasNoneFiles should be set when there are INSTRUCTION_UPDATE_METADATA
authorOlivier Goffart <ogoffart@woboq.com>
Wed, 20 Sep 2017 09:03:37 +0000 (11:03 +0200)
committerRoeland Jago Douma <roeland@famdouma.nl>
Thu, 5 Oct 2017 20:01:38 +0000 (22:01 +0200)
src/libsync/syncengine.cpp
test/testallfilesdeleted.cpp

index 80d36d4be3b4ffd2d01e8cf580a7c59046aed3f1..8bb33686581047f69ecdc2bbff98c609d058ac74 100644 (file)
@@ -555,7 +555,7 @@ int SyncEngine::treewalkFile(csync_file_stat_t *file, csync_file_stat_t *other,
     switch (file->instruction) {
     case CSYNC_INSTRUCTION_NONE: {
         // Any files that are instruction NONE?
-        if (!isDirectory && (!other || other->instruction == CSYNC_INSTRUCTION_NONE)) {
+        if (!isDirectory && (!other || other->instruction == CSYNC_INSTRUCTION_NONE || other->instruction == CSYNC_INSTRUCTION_UPDATE_METADATA)) {
             _hasNoneFiles = true;
         }
         // Put none-instruction conflict files into the syncfileitem list
@@ -614,6 +614,10 @@ int SyncEngine::treewalkFile(csync_file_stat_t *file, csync_file_stat_t *other,
                 _journal->updateLocalMetadata(item->_file, item->_modtime, item->_size, item->_inode);
             }
 
+            if (!other || other->instruction == CSYNC_INSTRUCTION_NONE || other->instruction == CSYNC_INSTRUCTION_UPDATE_METADATA) {
+                _hasNoneFiles = true;
+            }
+
             // Technically we're done with this item.
             return re;
         }
index d9356c8449ab2133d1d3e5b0e66668a64bc9c8ce..856fe73e3d9d8c55e4b6c86e3fd2bbbeb283ea3e 100644 (file)
 
 using namespace OCC;
 
+
+static void changeAllFileId(FileInfo &info) {
+    info.fileId = generateFileId();
+    if (!info.isDir)
+        return;
+    info.etag = generateEtag();
+    for (auto it = info.children.begin(); it != info.children.end(); ++it) {
+        changeAllFileId(*it);
+    }
+}
+
 /*
  * This test ensure that the SyncEngine::aboutToRemoveAllFiles is correctly called and that when
  * we the user choose to remove all files SyncJournalDb::clearFileTable makes works as expected
@@ -112,6 +123,34 @@ private slots:
         QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
         QCOMPARE(fakeFolder.currentLocalState().children.count(), 0);
     }
+
+    void testNotDeleteMetaDataChange() {
+        /**
+         * This test make sure that we don't popup a file deleted message if all the metadata have
+         * been updated (for example when the server is upgraded or something)
+         **/
+
+        FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
+        // We never remove all files.
+        QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveAllFiles,
+            [&] { QVERIFY(false); });
+        QVERIFY(fakeFolder.syncOnce());
+
+        for (const auto &s : fakeFolder.currentRemoteState().children.keys())
+            fakeFolder.syncJournal().avoidRenamesOnNextSync(s); // clears all the fileid and inodes.
+        fakeFolder.localModifier().remove("A/a1");
+        auto expectedState = fakeFolder.currentLocalState();
+        QVERIFY(fakeFolder.syncOnce());
+        QCOMPARE(fakeFolder.currentLocalState(), expectedState);
+        QCOMPARE(fakeFolder.currentRemoteState(), expectedState);
+
+        fakeFolder.remoteModifier().remove("B/b1");
+        changeAllFileId(fakeFolder.remoteModifier());
+        expectedState = fakeFolder.currentRemoteState();
+        QVERIFY(fakeFolder.syncOnce());
+        QCOMPARE(fakeFolder.currentLocalState(), expectedState);
+        QCOMPARE(fakeFolder.currentRemoteState(), expectedState);
+    }
 };
 
 QTEST_GUILESS_MAIN(TestAllFilesDeleted)