Virtual files: Renaming to virtual doesn't delete data #6718
authorChristian Kamm <mail@ckamm.de>
Thu, 16 Aug 2018 10:38:39 +0000 (12:38 +0200)
committerKevin Ottens <kevin.ottens@nextcloud.com>
Tue, 15 Dec 2020 09:58:03 +0000 (10:58 +0100)
Unfortunately to do this, the local update phase must write to the
database, creating a new side-effect and order dependency (local update
must run before remote update).

src/libsync/propagatedownload.cpp
test/testsyncvirtualfiles.cpp

index c6a42137141dbf1316771d1f5e721cd7736f0e8a..85e9d3867a0228a11391534269c59ab5d3b2dae0 100644 (file)
@@ -396,6 +396,8 @@ void PropagateDownloadFile::startAfterIsEncryptedIsChecked()
     if (_item->_type == ItemTypeVirtualFile) {
         auto fn = propagator()->getFilePath(_item->_file);
         qCDebug(lcPropagateDownload) << "creating virtual file" << fn;
+
+        // NOTE: Other places might depend on contents of placeholder files (like csync_update)
         QFile file(fn);
         file.open(QFile::ReadWrite | QFile::Truncate);
         file.write(" ");
index 4222509945cbb43105332301e9113b9e51c94df1..415c90220df7b2e0809357315d873574985d6eaf 100644 (file)
@@ -586,6 +586,42 @@ private slots:
         QVERIFY(fakeFolder.syncOnce());
         QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
     }
+
+    void testRenameToVirtual()
+    {
+        FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() };
+        SyncOptions syncOptions;
+        syncOptions._newFilesAreVirtual = true;
+        fakeFolder.syncEngine().setSyncOptions(syncOptions);
+        QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+        QSignalSpy completeSpy(&fakeFolder.syncEngine(), SIGNAL(itemCompleted(const SyncFileItemPtr &)));
+
+        auto cleanup = [&]() {
+            completeSpy.clear();
+        };
+        cleanup();
+
+        // If a file is renamed to <name>.owncloud, it becomes virtual
+        fakeFolder.localModifier().rename("A/a1", "A/a1.owncloud");
+        // If a file is renamed to <random>.owncloud, the file sticks around (to preserve user data)
+        fakeFolder.localModifier().rename("A/a2", "A/rand.owncloud");
+        QVERIFY(fakeFolder.syncOnce());
+
+        QVERIFY(!fakeFolder.currentLocalState().find("A/a1"));
+        QVERIFY(fakeFolder.currentLocalState().find("A/a1.owncloud"));
+        QVERIFY(fakeFolder.currentRemoteState().find("A/a1"));
+        QVERIFY(itemInstruction(completeSpy, "A/a1.owncloud", CSYNC_INSTRUCTION_NEW));
+        QCOMPARE(dbRecord(fakeFolder, "A/a1.owncloud")._type, ItemTypeVirtualFile);
+
+        QVERIFY(!fakeFolder.currentLocalState().find("A/a2"));
+        QVERIFY(!fakeFolder.currentLocalState().find("A/a2.owncloud"));
+        QVERIFY(fakeFolder.currentLocalState().find("A/rand.owncloud"));
+        QVERIFY(!fakeFolder.currentRemoteState().find("A/a2"));
+        QVERIFY(itemInstruction(completeSpy, "A/a2", CSYNC_INSTRUCTION_REMOVE));
+        QVERIFY(!dbRecord(fakeFolder, "A/rand.owncloud").isValid());
+
+        cleanup();
+    }
 };
 
 QTEST_GUILESS_MAIN(TestSyncVirtualFiles)