From b00a5934c912ce02e5d4b88ea7f0a4a607b85ea2 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 1e276ad689577..dfcb37d29001a 100644 --- a/src/libsync/discovery.cpp +++ b/src/libsync/discovery.cpp @@ -1085,14 +1085,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 1382f924c7116575aa21c7e7c238d649f89022f7 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 44759da6ad5d6..b561eb2c94e80 100644 --- a/test/testsyncvirtualfiles.cpp +++ b/test/testsyncvirtualfiles.cpp @@ -175,17 +175,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 0757e94b50f21ca775caf65f4af2afdd34acda21 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 2915e2517e26e2793c445d93341d37cedd5a9e6a 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 b561eb2c94e80..c90a55e322f61 100644 --- a/test/testsyncvirtualfiles.cpp +++ b/test/testsyncvirtualfiles.cpp @@ -182,7 +182,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