瀏覽代碼

Vfs: Ensure pins change with (de-)hydration

Previously an implicit hydration of a file in an online-only folder
would not change the pin state and cause a dehydration on the next
sync.
Christian Kamm 6 年之前
父節點
當前提交
00dcf3ef59
共有 3 個文件被更改,包括 55 次插入6 次删除
  1. 9 4
      src/libsync/propagatedownload.cpp
  2. 5 0
      src/libsync/vfs/suffix/vfs_suffix.cpp
  3. 41 2
      test/testsyncvirtualfiles.cpp

+ 9 - 4
src/libsync/propagatedownload.cpp

@@ -1017,11 +1017,11 @@ void PropagateDownloadFile::downloadFinished()
     if (_conflictRecord.isValid())
         propagator()->_journal->setConflictRecord(_conflictRecord);
 
-    if (_item->_type == ItemTypeVirtualFileDownload) {
+    auto vfs = propagator()->syncOptions()._vfs;
+    if (vfs && vfs->mode() == Vfs::WithSuffix) {
         // If the virtual file used to have a different name and db
-        // entry, wipe both now.
-        auto vfs = propagator()->syncOptions()._vfs;
-        if (vfs && vfs->mode() == Vfs::WithSuffix) {
+        // entry, remove it transfer its old pin state.
+        if (_item->_type == ItemTypeVirtualFileDownload) {
             QString virtualFile = _item->_file + vfs->fileSuffix();
             auto fn = propagator()->getFilePath(virtualFile);
             qCDebug(lcPropagateDownload) << "Download of previous virtual file finished" << fn;
@@ -1035,6 +1035,11 @@ void PropagateDownloadFile::downloadFinished()
                 vfs->setPinState(virtualFile, PinState::Inherited);
             }
         }
+
+        // Ensure the pin state isn't contradictory
+        auto pin = vfs->pinState(_item->_file);
+        if (pin && *pin == PinState::OnlineOnly)
+            vfs->setPinState(_item->_file, PinState::Unspecified);
     }
 
     updateMetadata(isConflict);

+ 5 - 0
src/libsync/vfs/suffix/vfs_suffix.cpp

@@ -89,6 +89,11 @@ void VfsSuffix::dehydratePlaceholder(const SyncFileItem &item)
         setPinState(item._renameTarget, *pin);
         setPinState(item._file, PinState::Inherited);
     }
+
+    // Ensure the pin state isn't contradictory
+    pin = pinState(item._renameTarget);
+    if (pin && *pin == PinState::AlwaysLocal)
+        setPinState(item._renameTarget, PinState::Unspecified);
 }
 
 void VfsSuffix::convertToPlaceholder(const QString &, const SyncFileItem &, const QString &)

+ 41 - 2
test/testsyncvirtualfiles.cpp

@@ -718,11 +718,11 @@ private slots:
         // Case 4: foo -> bar.oc (db unchanged)
         fakeFolder.localModifier().rename("case4", "case4-rename" DVSUFFIX);
 
-        // Case 5: foo -> bar (db dehydrate)
+        // Case 5: foo.oc -> bar.oc (db hydrate)
         fakeFolder.localModifier().rename("case5" DVSUFFIX, "case5-rename" DVSUFFIX);
         triggerDownload(fakeFolder, "case5");
 
-        // Case 6: foo.oc -> bar.oc (db hydrate)
+        // Case 6: foo -> bar (db dehydrate)
         fakeFolder.localModifier().rename("case6", "case6-rename");
         markForDehydration(fakeFolder, "case6");
 
@@ -1175,6 +1175,45 @@ private slots:
         QVERIFY(fakeFolder.currentLocalState().find("onlinerenamed2/file1rename" DVSUFFIX));
         QCOMPARE(*vfs->pinState("onlinerenamed2/file1rename" DVSUFFIX), PinState::OnlineOnly);
     }
+
+    void testIncompatiblePins()
+    {
+        FakeFolder fakeFolder{ FileInfo() };
+        auto vfs = setupVfs(fakeFolder);
+        QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+
+        auto setPin = [&] (const QByteArray &path, PinState state) {
+            fakeFolder.syncJournal().internalPinStates().setForPath(path, state);
+        };
+
+        fakeFolder.remoteModifier().mkdir("local");
+        fakeFolder.remoteModifier().mkdir("online");
+        QVERIFY(fakeFolder.syncOnce());
+        QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+
+        setPin("local", PinState::AlwaysLocal);
+        setPin("online", PinState::OnlineOnly);
+
+        fakeFolder.localModifier().insert("local/file1");
+        fakeFolder.localModifier().insert("online/file1");
+        QVERIFY(fakeFolder.syncOnce());
+
+        markForDehydration(fakeFolder, "local/file1");
+        triggerDownload(fakeFolder, "online/file1");
+
+        // the sync sets the changed files pin states to unspecified
+        QVERIFY(fakeFolder.syncOnce());
+
+        QVERIFY(fakeFolder.currentLocalState().find("online/file1"));
+        QVERIFY(fakeFolder.currentLocalState().find("local/file1" DVSUFFIX));
+        QCOMPARE(*vfs->pinState("online/file1"), PinState::Unspecified);
+        QCOMPARE(*vfs->pinState("local/file1" DVSUFFIX), PinState::Unspecified);
+
+        // no change on another sync
+        QVERIFY(fakeFolder.syncOnce());
+        QVERIFY(fakeFolder.currentLocalState().find("online/file1"));
+        QVERIFY(fakeFolder.currentLocalState().find("local/file1" DVSUFFIX));
+    }
 };
 
 QTEST_GUILESS_MAIN(TestSyncVirtualFiles)