Virtual files: Only remove virtual file once on download
authorChristian Kamm <mail@ckamm.de>
Tue, 29 May 2018 11:16:58 +0000 (13:16 +0200)
committerKevin Ottens <kevin.ottens@nextcloud.com>
Tue, 15 Dec 2020 09:57:54 +0000 (10:57 +0100)
With thanks to @ogoffart for spotting the problem.

src/csync/csync_reconcile.cpp
test/testsyncvirtualfiles.cpp

index 4c884083aa48542459e7306fd6be8ff31c6bdcea..54a4ac2712b06a34338e129814743623da4ad952 100644 (file)
@@ -185,6 +185,25 @@ static void _csync_merge_algorithm_visitor(csync_file_stat_t *cur, CSYNC * ctx)
                 cur->instruction = CSYNC_INSTRUCTION_NEW;
                 break;
             }
+
+            /* If a virtual file is supposed to be downloaded, the local tree
+             * will see "foo.owncloud" NONE while the remote might see "foo".
+             * In the common case of remote NEW we don't want to trigger the REMOVE
+             * that would normally be done for foo.owncloud since the download for
+             * "foo" will take care of it.
+             * If it was removed remotely, or moved remotely, the REMOVE is what we want.
+             */
+            if (cur->type == ItemTypeVirtualFileDownload
+                && ctx->current == LOCAL_REPLICA
+                && cur->path.endsWith(ctx->virtual_file_suffix)) {
+                auto actualOther = other_tree->findFile(cur->path.left(cur->path.size() - ctx->virtual_file_suffix.size()));
+                if (actualOther
+                    && (actualOther->instruction == CSYNC_INSTRUCTION_NEW
+                        || actualOther->instruction == CSYNC_INSTRUCTION_CONFLICT)) {
+                    cur->instruction = CSYNC_INSTRUCTION_NONE;
+                    break;
+                }
+            }
             cur->instruction = CSYNC_INSTRUCTION_REMOVE;
             break;
         case CSYNC_INSTRUCTION_EVAL_RENAME: {
index 8ec09a6f8c70bf1924ef8f552521596e8752475d..ba162836f918759829083fa0ccbcd357afcdcb65 100644 (file)
@@ -330,14 +330,14 @@ private slots:
         fakeFolder.localModifier().remove("A/a6.owncloud");
         QVERIFY(fakeFolder.syncOnce());
         QVERIFY(itemInstruction(completeSpy, "A/a1", CSYNC_INSTRUCTION_NEW));
-        QVERIFY(itemInstruction(completeSpy, "A/a1.owncloud", CSYNC_INSTRUCTION_REMOVE));
+        QVERIFY(itemInstruction(completeSpy, "A/a1.owncloud", CSYNC_INSTRUCTION_NONE));
         QVERIFY(itemInstruction(completeSpy, "A/a2", CSYNC_INSTRUCTION_NEW));
-        QVERIFY(itemInstruction(completeSpy, "A/a2.owncloud", CSYNC_INSTRUCTION_REMOVE));
+        QVERIFY(itemInstruction(completeSpy, "A/a2.owncloud", CSYNC_INSTRUCTION_NONE));
         QVERIFY(itemInstruction(completeSpy, "A/a3.owncloud", CSYNC_INSTRUCTION_REMOVE));
-        QVERIFY(itemInstruction(completeSpy, "A/a4.owncloud", CSYNC_INSTRUCTION_REMOVE));
         QVERIFY(itemInstruction(completeSpy, "A/a4m", CSYNC_INSTRUCTION_NEW));
+        QVERIFY(itemInstruction(completeSpy, "A/a4.owncloud", CSYNC_INSTRUCTION_REMOVE));
         QVERIFY(itemInstruction(completeSpy, "A/a5", CSYNC_INSTRUCTION_CONFLICT));
-        QVERIFY(itemInstruction(completeSpy, "A/a5.owncloud", CSYNC_INSTRUCTION_REMOVE));
+        QVERIFY(itemInstruction(completeSpy, "A/a5.owncloud", CSYNC_INSTRUCTION_NONE));
         QVERIFY(itemInstruction(completeSpy, "A/a6", CSYNC_INSTRUCTION_CONFLICT));
         QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
         QCOMPARE(dbRecord(fakeFolder, "A/a1")._type, ItemTypeFile);