From 908066072af3017cfa35cc2ef8aabd221199203b Mon Sep 17 00:00:00 2001 From: Matthieu Gallien Date: Wed, 30 Mar 2022 19:11:35 +0200 Subject: [PATCH] avoid deleting renamed file with spaces in name ensure that normal sync engine will nto delete new file renamed due to trailing/leading spaces in name rename before upload in the same job to avoid having invalid state in local desktop client database to ensure any subsequent run of the sync engine will not make wrong decisions Signed-off-by: Matthieu Gallien --- src/libsync/discovery.cpp | 4 ++++ src/libsync/propagateremotemkdir.cpp | 13 +++++++++++++ src/libsync/propagateupload.cpp | 12 ++++++++++++ test/testlocaldiscovery.cpp | 10 ++++++++++ 4 files changed, 39 insertions(+) diff --git a/src/libsync/discovery.cpp b/src/libsync/discovery.cpp index a7e41d8bc..63b75a05f 100644 --- a/src/libsync/discovery.cpp +++ b/src/libsync/discovery.cpp @@ -1054,6 +1054,10 @@ void ProcessDirectoryJob::processFileAnalyzeLocalInfo( if (!localEntry.renameName.isEmpty()) { handleInvalidSpaceRename(SyncFileItem::Down); + item->_instruction = CSYNC_INSTRUCTION_NEW; + item->_direction = SyncFileItem::Up; + item->_originalFile = item->_file; + item->_file = item->_renameTarget; finalize(); return; } diff --git a/src/libsync/propagateremotemkdir.cpp b/src/libsync/propagateremotemkdir.cpp index ac1b5b62a..f95fbca01 100644 --- a/src/libsync/propagateremotemkdir.cpp +++ b/src/libsync/propagateremotemkdir.cpp @@ -20,6 +20,7 @@ #include "deletejob.h" #include "common/asserts.h" #include "encryptfolderjob.h" +#include "filesystem.h" #include #include @@ -169,6 +170,18 @@ void PropagateRemoteMkdir::finalizeMkColJob(QNetworkReply::NetworkError err, con void PropagateRemoteMkdir::slotMkdir() { + if (!_item->_originalFile.isEmpty() && !_item->_renameTarget.isEmpty() && _item->_renameTarget != _item->_originalFile) { + const auto existingFile = propagator()->fullLocalPath(propagator()->adjustRenamedPath(_item->_originalFile)); + const auto targetFile = propagator()->fullLocalPath(_item->_renameTarget); + QString renameError; + if (!FileSystem::rename(existingFile, targetFile, &renameError)) { + done(SyncFileItem::NormalError, renameError); + return; + } + emit propagator()->touchedFile(existingFile); + emit propagator()->touchedFile(targetFile); + } + const auto path = _item->_file; const auto slashPosition = path.lastIndexOf('/'); const auto parentPath = slashPosition >= 0 ? path.left(slashPosition) : QString(); diff --git a/src/libsync/propagateupload.cpp b/src/libsync/propagateupload.cpp index 7a6a124ed..829dc529d 100644 --- a/src/libsync/propagateupload.cpp +++ b/src/libsync/propagateupload.cpp @@ -194,6 +194,18 @@ void PropagateUploadFileCommon::setDeleteExisting(bool enabled) void PropagateUploadFileCommon::start() { + if (!_item->_originalFile.isEmpty() && !_item->_renameTarget.isEmpty() && _item->_renameTarget != _item->_originalFile) { + const auto existingFile = propagator()->fullLocalPath(propagator()->adjustRenamedPath(_item->_originalFile)); + const auto targetFile = propagator()->fullLocalPath(_item->_renameTarget); + QString renameError; + if (!FileSystem::rename(existingFile, targetFile, &renameError)) { + done(SyncFileItem::NormalError, renameError); + return; + } + emit propagator()->touchedFile(existingFile); + emit propagator()->touchedFile(targetFile); + } + const auto path = _item->_file; const auto slashPosition = path.lastIndexOf('/'); const auto parentPath = slashPosition >= 0 ? path.left(slashPosition) : QString(); diff --git a/test/testlocaldiscovery.cpp b/test/testlocaldiscovery.cpp index fa714129d..d84f95345 100644 --- a/test/testlocaldiscovery.cpp +++ b/test/testlocaldiscovery.cpp @@ -223,6 +223,7 @@ private slots: fakeFolder.localModifier().insert(fileWithSpaces4); fakeFolder.localModifier().insert(fileWithSpaces5); fakeFolder.localModifier().insert(fileWithSpaces6); + fakeFolder.localModifier().mkdir(QStringLiteral(" with spaces ")); QVERIFY(fakeFolder.syncOnce()); @@ -244,6 +245,10 @@ private slots: QVERIFY(fakeFolder.currentLocalState().find("A/bla")); QVERIFY(!fakeFolder.currentLocalState().find(fileWithSpaces6)); + QVERIFY(fakeFolder.currentLocalState().find(QStringLiteral("with spaces"))); + QVERIFY(!fakeFolder.currentLocalState().find(QStringLiteral(" with spaces "))); + + fakeFolder.syncEngine().setLocalDiscoveryOptions(LocalDiscoveryStyle::DatabaseAndFilesystem, {QStringLiteral("foo"), QStringLiteral("bar"), QStringLiteral("bla"), QStringLiteral("A/foo"), QStringLiteral("A/bar"), QStringLiteral("A/bla")}); QVERIFY(fakeFolder.syncOnce()); QVERIFY(fakeFolder.currentRemoteState().find(fileWithSpaces1.trimmed())); @@ -275,6 +280,11 @@ private slots: QVERIFY(!fakeFolder.currentRemoteState().find(fileWithSpaces6)); QVERIFY(fakeFolder.currentLocalState().find("A/bla")); QVERIFY(!fakeFolder.currentLocalState().find(fileWithSpaces6)); + + QVERIFY(fakeFolder.currentRemoteState().find(QStringLiteral("with spaces"))); + QVERIFY(!fakeFolder.currentRemoteState().find(QStringLiteral(" with spaces "))); + QVERIFY(fakeFolder.currentLocalState().find(QStringLiteral("with spaces"))); + QVERIFY(!fakeFolder.currentLocalState().find(QStringLiteral(" with spaces "))); } void testCreateFileWithTrailingSpaces_localAndRemoteTrimmedDoNotExist_renameFile() -- 2.30.2