From 20c1c226d52805b5e5e9ba1cdb92f4d652e74c5d Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Mon, 17 Jun 2024 23:40:28 +0800 Subject: [PATCH 1/4] Allow deletion of virtual suffix placeholder files Signed-off-by: Claudio Cambra --- src/libsync/discovery.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/libsync/discovery.cpp b/src/libsync/discovery.cpp index 858e1b207d9a2..7b6b93bb1c812 100644 --- a/src/libsync/discovery.cpp +++ b/src/libsync/discovery.cpp @@ -1082,14 +1082,6 @@ void ProcessDirectoryJob::processFileAnalyzeLocalInfo( qCWarning(lcDisco) << "Failed to delete a file record from the local DB" << path._original; } return; - } else if (dbEntry._type == ItemTypeVirtualFile && isVfsWithSuffix()) { - // If the virtual file is removed, recreate it. - // This is a precaution since the suffix files don't look like the real ones - // and we don't want users to accidentally delete server data because they - // might not expect that deleting the placeholder will have a remote effect. - item->_instruction = CSYNC_INSTRUCTION_NEW; - item->_direction = SyncFileItem::Down; - item->_type = ItemTypeVirtualFile; } else if (!serverModified) { // Removed locally: also remove on the server. if (!dbEntry._serverHasIgnoredFiles) { From df5b94c4319afa9285fc69b0186f53830198da68 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Tue, 25 Jun 2024 23:26:15 +0800 Subject: [PATCH 2/4] Amend behaviour of suffix virtual files test to reflect new expected behaviour Signed-off-by: Claudio Cambra --- test/testsyncvirtualfiles.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/test/testsyncvirtualfiles.cpp b/test/testsyncvirtualfiles.cpp index c6e9dab8b99d2..29f03c29a9769 100644 --- a/test/testsyncvirtualfiles.cpp +++ b/test/testsyncvirtualfiles.cpp @@ -167,17 +167,14 @@ private slots: QCOMPARE(dbRecord(fakeFolder, "A/a1" DVSUFFIX)._fileSize, 65); cleanup(); - // If the local virtual file file is removed, it'll just be recreated + // If the local virtual file is removed, it should be gone remotely too if (!doLocalDiscovery) fakeFolder.syncEngine().setLocalDiscoveryOptions(LocalDiscoveryStyle::DatabaseAndFilesystem, { "A" }); fakeFolder.localModifier().remove("A/a1" DVSUFFIX); QVERIFY(fakeFolder.syncOnce()); QVERIFY(!fakeFolder.currentLocalState().find("A/a1")); - QVERIFY(fakeFolder.currentLocalState().find("A/a1" DVSUFFIX)); - QVERIFY(fakeFolder.currentRemoteState().find("A/a1")); - QVERIFY(itemInstruction(completeSpy, "A/a1" DVSUFFIX, CSYNC_INSTRUCTION_NEW)); - QCOMPARE(dbRecord(fakeFolder, "A/a1" DVSUFFIX)._type, ItemTypeVirtualFile); - QCOMPARE(dbRecord(fakeFolder, "A/a1" DVSUFFIX)._fileSize, 65); + QVERIFY(!fakeFolder.currentLocalState().find("A/a1" DVSUFFIX)); + QVERIFY(!fakeFolder.currentRemoteState().find("A/a1")); cleanup(); // Remote rename is propagated From fa735fdac4b42d88343f5fc4df1c2200342de5bf Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Wed, 26 Jun 2024 15:07:23 +0800 Subject: [PATCH 3/4] Ensure stripping of suffix vfs placeholder file's suffix when issuing delete command to server Signed-off-by: Claudio Cambra --- src/libsync/propagateremotedelete.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/libsync/propagateremotedelete.cpp b/src/libsync/propagateremotedelete.cpp index 306ed4b1d73bf..7bc5be9528889 100644 --- a/src/libsync/propagateremotedelete.cpp +++ b/src/libsync/propagateremotedelete.cpp @@ -58,12 +58,19 @@ void PropagateRemoteDelete::start() void PropagateRemoteDelete::createDeleteJob(const QString &filename) { - qCInfo(lcPropagateRemoteDelete) << "Deleting file, local" << _item->_file << "remote" << filename; + Q_ASSERT(propagator()); + auto remoteFilename = filename; + if (_item->_type == ItemType::ItemTypeVirtualFile) { + if (const auto vfs = propagator()->syncOptions()._vfs; vfs->mode() == Vfs::Mode::WithSuffix) { + // These are compile-time constants so no need to recreate each time + static constexpr auto suffixSize = std::string_view(APPLICATION_DOTVIRTUALFILE_SUFFIX).size(); + remoteFilename.chop(suffixSize); + } + } - _job = new DeleteJob(propagator()->account(), - propagator()->fullRemotePath(filename), - this); + qCInfo(lcPropagateRemoteDelete) << "Deleting file, local" << _item->_file << "remote" << remoteFilename; + _job = new DeleteJob(propagator()->account(), propagator()->fullRemotePath(remoteFilename), this); connect(_job.data(), &DeleteJob::finishedSignal, this, &PropagateRemoteDelete::slotDeleteJobFinished); propagator()->_activeJobList.append(this); _job->start(); From f843b5c36206d4bec03a824404cb051208da04b7 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Wed, 26 Jun 2024 15:07:50 +0800 Subject: [PATCH 4/4] Properly reset fakefolder test state post-placeholder file delete in testsyncvirtualfiles Signed-off-by: Claudio Cambra --- test/testsyncvirtualfiles.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/test/testsyncvirtualfiles.cpp b/test/testsyncvirtualfiles.cpp index 29f03c29a9769..d4f3275726054 100644 --- a/test/testsyncvirtualfiles.cpp +++ b/test/testsyncvirtualfiles.cpp @@ -174,7 +174,20 @@ private slots: QVERIFY(fakeFolder.syncOnce()); QVERIFY(!fakeFolder.currentLocalState().find("A/a1")); QVERIFY(!fakeFolder.currentLocalState().find("A/a1" DVSUFFIX)); - QVERIFY(!fakeFolder.currentRemoteState().find("A/a1")); + QVERIFY(!fakeFolder.remoteModifier().find("A/a1")); + cleanup(); + + // Restore the state prior to next test + // Essentially repeating creation of virtual file + fakeFolder.remoteModifier().insert("A/a1", 64); + fakeFolder.remoteModifier().setModTime("A/a1", someDate); + QVERIFY(fakeFolder.syncOnce()); + QVERIFY(!fakeFolder.currentLocalState().find("A/a1")); + QVERIFY(fakeFolder.currentLocalState().find("A/a1" DVSUFFIX)); + QCOMPARE(QFileInfo(fakeFolder.localPath() + "A/a1" DVSUFFIX).lastModified(), someDate); + QVERIFY(fakeFolder.currentRemoteState().find("A/a1")); + QVERIFY(itemInstruction(completeSpy, "A/a1" DVSUFFIX, CSYNC_INSTRUCTION_NEW)); + QCOMPARE(dbRecord(fakeFolder, "A/a1" DVSUFFIX)._type, ItemTypeVirtualFile); cleanup(); // Remote rename is propagated