Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/desktop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libsync/discovery.cpp74
-rw-r--r--src/libsync/discoveryphase.h1
-rw-r--r--src/libsync/propagateremotemove.cpp11
-rw-r--r--src/libsync/propagateupload.cpp20
-rw-r--r--test/testlocaldiscovery.cpp72
-rw-r--r--test/testsyncvirtualfiles.cpp117
6 files changed, 261 insertions, 34 deletions
diff --git a/src/libsync/discovery.cpp b/src/libsync/discovery.cpp
index 01cd608cd..ded16cc98 100644
--- a/src/libsync/discovery.cpp
+++ b/src/libsync/discovery.cpp
@@ -41,7 +41,7 @@ Q_LOGGING_CATEGORY(lcDisco, "sync.discovery", QtInfoMsg)
bool ProcessDirectoryJob::checkForInvalidFileName(const PathTuple &path,
const std::map<QString, Entries> &entries, Entries &entry)
{
- const auto originalFileName = entry.localEntry.name;
+ const auto originalFileName = entry.localEntry.isValid() ? entry.localEntry.name : entry.serverEntry.name;
const auto newFileName = originalFileName.trimmed();
if (originalFileName == newFileName) {
@@ -61,7 +61,7 @@ bool ProcessDirectoryJob::checkForInvalidFileName(const PathTuple &path,
if (!errorMessage.isEmpty()) {
auto item = SyncFileItemPtr::create();
- if (entry.localEntry.isDirectory) {
+ if ((entry.localEntry.isValid() && entry.localEntry.isDirectory) || (entry.serverEntry.isValid() && entry.serverEntry.isDirectory)) {
item->_type = CSyncEnums::ItemTypeDirectory;
} else {
item->_type = CSyncEnums::ItemTypeFile;
@@ -76,7 +76,11 @@ bool ProcessDirectoryJob::checkForInvalidFileName(const PathTuple &path,
}
}
- entry.localEntry.renameName = newFileName;
+ if (entry.localEntry.isValid()) {
+ entry.localEntry.renameName = newFileName;
+ } else {
+ entry.serverEntry.renameName = newFileName;
+ }
return true;
}
@@ -389,13 +393,6 @@ void ProcessDirectoryJob::processFile(PathTuple path,
item->_originalFile = path._original;
item->_previousSize = dbEntry._fileSize;
item->_previousModtime = dbEntry._modtime;
- if (!localEntry.renameName.isEmpty()) {
- if (_dirItem) {
- item->_renameTarget = _dirItem->_file + "/" + localEntry.renameName;
- } else {
- item->_renameTarget = localEntry.renameName;
- }
- }
if (dbEntry._modtime == localEntry.modtime && dbEntry._type == ItemTypeVirtualFile && localEntry.type == ItemTypeFile) {
item->_type = ItemTypeFile;
@@ -602,6 +599,22 @@ void ProcessDirectoryJob::processFileAnalyzeRemoteInfo(
// Unknown in db: new file on the server
Q_ASSERT(!dbEntry.isValid());
+ if (!serverEntry.renameName.isEmpty()) {
+ item->_renameTarget = _dirItem ? _dirItem->_file + "/" + serverEntry.renameName : serverEntry.renameName;
+ item->_originalFile = path._original;
+ item->_modtime = serverEntry.modtime;
+ item->_size = serverEntry.size;
+ item->_instruction = CSYNC_INSTRUCTION_RENAME;
+ item->_direction = SyncFileItem::Up;
+ item->_fileId = serverEntry.fileId;
+ item->_remotePerm = serverEntry.remotePerm;
+ item->_etag = serverEntry.etag;
+ item->_type = serverEntry.isDirectory ? CSyncEnums::ItemTypeDirectory : CSyncEnums::ItemTypeFile;
+
+ processFileAnalyzeLocalInfo(item, path, localEntry, serverEntry, dbEntry, _queryServer);
+ return;
+ }
+
item->_instruction = CSYNC_INSTRUCTION_NEW;
item->_direction = SyncFileItem::Down;
item->_modtime = serverEntry.modtime;
@@ -1005,6 +1018,42 @@ void ProcessDirectoryJob::processFileAnalyzeLocalInfo(
return;
}
+ if (!localEntry.renameName.isEmpty()) {
+ if (_dirItem) {
+ path._target = _dirItem->_file + "/" + localEntry.renameName;
+ } else {
+ path._target = localEntry.renameName;
+ }
+ OCC::SyncJournalFileRecord base;
+ if (!_discoveryData->_statedb->getFileRecordByInode(localEntry.inode, &base)) {
+ dbError();
+ return;
+ }
+ const auto originalPath = base.path();
+ const auto adjustedOriginalPath = _discoveryData->adjustRenamedPath(originalPath, SyncFileItem::Down);
+ _discoveryData->_renamedItemsLocal.insert(originalPath, path._target);
+ item->_renameTarget = path._target;
+ path._server = adjustedOriginalPath;
+ if (_dirItem) {
+ item->_file = _dirItem->_file + "/" + localEntry.name;
+ } else {
+ item->_file = localEntry.name;
+ }
+ path._original = originalPath;
+ item->_originalFile = path._original;
+ item->_modtime = base._modtime;
+ item->_inode = base._inode;
+ item->_instruction = CSYNC_INSTRUCTION_RENAME;
+ item->_direction = SyncFileItem::Down;
+ item->_fileId = base._fileId;
+ item->_remotePerm = base._remotePerm;
+ item->_etag = base._etag;
+ item->_type = base._type;
+
+ finalize();
+ return;
+ }
+
// New local file or rename
item->_instruction = CSYNC_INSTRUCTION_NEW;
item->_direction = SyncFileItem::Up;
@@ -1341,10 +1390,11 @@ void ProcessDirectoryJob::processFileFinalize(
if (isVfsWithSuffix()) {
if (item->_type == ItemTypeVirtualFile) {
addVirtualFileSuffix(path._target);
- if (item->_instruction == CSYNC_INSTRUCTION_RENAME)
+ if (item->_instruction == CSYNC_INSTRUCTION_RENAME) {
addVirtualFileSuffix(item->_renameTarget);
- else
+ } else {
addVirtualFileSuffix(item->_file);
+ }
}
if (item->_type == ItemTypeVirtualFileDehydration
&& item->_instruction == CSYNC_INSTRUCTION_SYNC) {
diff --git a/src/libsync/discoveryphase.h b/src/libsync/discoveryphase.h
index c894cfc2a..f5950e8dc 100644
--- a/src/libsync/discoveryphase.h
+++ b/src/libsync/discoveryphase.h
@@ -49,6 +49,7 @@ struct RemoteInfo
{
/** FileName of the entry (this does not contains any directory or path, just the plain name */
QString name;
+ QString renameName;
QByteArray etag;
QByteArray fileId;
QByteArray checksumHeader;
diff --git a/src/libsync/propagateremotemove.cpp b/src/libsync/propagateremotemove.cpp
index edd29306c..5f5cdd06e 100644
--- a/src/libsync/propagateremotemove.cpp
+++ b/src/libsync/propagateremotemove.cpp
@@ -19,6 +19,7 @@
#include "common/syncjournalfilerecord.h"
#include "filesystem.h"
#include "common/asserts.h"
+#include <QFileInfo>
#include <QFile>
#include <QStringList>
#include <QDir>
@@ -79,7 +80,7 @@ void PropagateRemoteMove::start()
return;
QString origin = propagator()->adjustRenamedPath(_item->_file);
- qCDebug(lcPropagateRemoteMove) << origin << _item->_renameTarget;
+ qCInfo(lcPropagateRemoteMove) << origin << _item->_renameTarget;
QString targetFile(propagator()->fullLocalPath(_item->_renameTarget));
@@ -254,6 +255,14 @@ void PropagateRemoteMove::finalize()
newItem._size = oldRecord._fileSize;
}
}
+
+ const auto targetFile = propagator()->fullLocalPath(_item->_renameTarget);
+ if (!QFileInfo::exists(targetFile)) {
+ propagator()->_journal->commit("Remote Rename");
+ done(SyncFileItem::Success);
+ return;
+ }
+
const auto result = propagator()->updateMetadata(newItem);
if (!result) {
done(SyncFileItem::FatalError, tr("Error updating metadata: %1").arg(result.error()));
diff --git a/src/libsync/propagateupload.cpp b/src/libsync/propagateupload.cpp
index cf4e4fc7c..7a6a124ed 100644
--- a/src/libsync/propagateupload.cpp
+++ b/src/libsync/propagateupload.cpp
@@ -198,26 +198,6 @@ void PropagateUploadFileCommon::start()
const auto slashPosition = path.lastIndexOf('/');
const auto parentPath = slashPosition >= 0 ? path.left(slashPosition) : QString();
-
- if (!_item->_renameTarget.isEmpty() && _item->_file != _item->_renameTarget) {
- // Try to rename the file
- const auto originalFilePathAbsolute = propagator()->fullLocalPath(_item->_file);
- const auto newFilePathAbsolute = propagator()->fullLocalPath(_item->_renameTarget);
- const auto renameSuccess = QFile::rename(originalFilePathAbsolute, newFilePathAbsolute);
- if (!renameSuccess) {
- done(SyncFileItem::NormalError, "File contains trailing spaces and couldn't be renamed");
- return;
- }
- _item->_file = _item->_renameTarget;
- _item->_modtime = FileSystem::getModTime(newFilePathAbsolute);
- Q_ASSERT(_item->_modtime > 0);
- if (_item->_modtime <= 0) {
- qCWarning(lcPropagateUpload()) << "invalid modified time" << _item->_file << _item->_modtime;
- slotOnErrorStartFolderUnlock(SyncFileItem::NormalError, tr("File %1 has invalid modified time. Do not upload to the server.").arg(QDir::toNativeSeparators(_item->_file)));
- return;
- }
- }
-
SyncJournalFileRecord parentRec;
bool ok = propagator()->_journal->getFileRecord(parentPath, &parentRec);
if (!ok) {
diff --git a/test/testlocaldiscovery.cpp b/test/testlocaldiscovery.cpp
index 15e4898df..90499bfc9 100644
--- a/test/testlocaldiscovery.cpp
+++ b/test/testlocaldiscovery.cpp
@@ -207,7 +207,7 @@ private slots:
void testCreateFileWithTrailingSpaces_localAndRemoteTrimmedDoNotExist_renameAndUploadFile()
{
- FakeFolder fakeFolder { FileInfo::A12_B12_C12_S12() };
+ FakeFolder fakeFolder{FileInfo{}};
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
const QString fileWithSpaces1(" foo");
const QString fileWithSpaces2(" bar ");
@@ -219,12 +219,33 @@ private slots:
fakeFolder.localModifier().insert(fileWithSpaces1);
fakeFolder.localModifier().insert(fileWithSpaces2);
fakeFolder.localModifier().insert(fileWithSpaces3);
+ fakeFolder.localModifier().mkdir("A");
fakeFolder.localModifier().insert(fileWithSpaces4);
fakeFolder.localModifier().insert(fileWithSpaces5);
fakeFolder.localModifier().insert(fileWithSpaces6);
QVERIFY(fakeFolder.syncOnce());
+ QVERIFY(fakeFolder.currentLocalState().find(fileWithSpaces1.trimmed()));
+ QVERIFY(!fakeFolder.currentLocalState().find(fileWithSpaces1));
+
+ QVERIFY(fakeFolder.currentLocalState().find(fileWithSpaces2.trimmed()));
+ QVERIFY(!fakeFolder.currentLocalState().find(fileWithSpaces2));
+
+ QVERIFY(fakeFolder.currentLocalState().find(fileWithSpaces3.trimmed()));
+ QVERIFY(!fakeFolder.currentLocalState().find(fileWithSpaces3));
+
+ QVERIFY(fakeFolder.currentLocalState().find("A/foo"));
+ QVERIFY(!fakeFolder.currentLocalState().find(fileWithSpaces4));
+
+ QVERIFY(fakeFolder.currentLocalState().find("A/bar"));
+ QVERIFY(!fakeFolder.currentLocalState().find(fileWithSpaces5));
+
+ QVERIFY(fakeFolder.currentLocalState().find("A/bla"));
+ QVERIFY(!fakeFolder.currentLocalState().find(fileWithSpaces6));
+
+ QVERIFY(fakeFolder.syncOnce());
+
QVERIFY(fakeFolder.currentRemoteState().find(fileWithSpaces1.trimmed()));
QVERIFY(!fakeFolder.currentRemoteState().find(fileWithSpaces1));
QVERIFY(fakeFolder.currentLocalState().find(fileWithSpaces1.trimmed()));
@@ -256,6 +277,55 @@ private slots:
QVERIFY(!fakeFolder.currentLocalState().find(fileWithSpaces6));
}
+ void testCreateFileWithTrailingSpaces_localAndRemoteTrimmedDoNotExist_renameFile()
+ {
+ FakeFolder fakeFolder{FileInfo{}};
+ QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+ const QString fileWithSpaces4("A/ foo");
+ const QString fileWithSpaces5("A/ bar ");
+ const QString fileWithSpaces6("A/bla ");
+
+ fakeFolder.remoteModifier().mkdir("A");
+ fakeFolder.remoteModifier().insert(fileWithSpaces4);
+ fakeFolder.remoteModifier().insert(fileWithSpaces5);
+ fakeFolder.remoteModifier().insert(fileWithSpaces6);
+
+ qDebug() << fakeFolder.currentRemoteState();
+
+ QVERIFY(fakeFolder.syncOnce());
+
+ qDebug() << fakeFolder.currentRemoteState();
+
+ QVERIFY(fakeFolder.currentRemoteState().find("A/foo"));
+ QVERIFY(!fakeFolder.currentRemoteState().find(fileWithSpaces4));
+
+ QVERIFY(fakeFolder.currentRemoteState().find("A/bar"));
+ QVERIFY(!fakeFolder.currentRemoteState().find(fileWithSpaces5));
+
+ QVERIFY(fakeFolder.currentRemoteState().find("A/bla"));
+ QVERIFY(!fakeFolder.currentRemoteState().find(fileWithSpaces6));
+
+ QVERIFY(fakeFolder.syncOnce());
+
+ QVERIFY(fakeFolder.currentRemoteState().find("A/foo"));
+ QVERIFY(!fakeFolder.currentRemoteState().find(fileWithSpaces4));
+ QVERIFY(fakeFolder.currentLocalState().find("A/foo"));
+ QVERIFY(!fakeFolder.currentLocalState().find(fileWithSpaces4));
+
+ QVERIFY(fakeFolder.currentRemoteState().find("A/bar"));
+ QVERIFY(!fakeFolder.currentRemoteState().find(fileWithSpaces5));
+ QVERIFY(fakeFolder.currentLocalState().find("A/bar"));
+ QVERIFY(!fakeFolder.currentLocalState().find(fileWithSpaces5));
+
+ QVERIFY(fakeFolder.currentRemoteState().find("A/bla"));
+ QVERIFY(!fakeFolder.currentRemoteState().find(fileWithSpaces6));
+ QVERIFY(fakeFolder.currentLocalState().find("A/bla"));
+ QVERIFY(!fakeFolder.currentLocalState().find(fileWithSpaces6));
+
+ auto expectedState = fakeFolder.currentLocalState();
+ QCOMPARE(fakeFolder.currentRemoteState(), expectedState);
+ }
+
void testCreateFileWithTrailingSpaces_localTrimmedDoesExist_dontRenameAndUploadFile()
{
FakeFolder fakeFolder { FileInfo::A12_B12_C12_S12() };
diff --git a/test/testsyncvirtualfiles.cpp b/test/testsyncvirtualfiles.cpp
index 5505c1f26..882879c7b 100644
--- a/test/testsyncvirtualfiles.cpp
+++ b/test/testsyncvirtualfiles.cpp
@@ -763,6 +763,123 @@ private slots:
QVERIFY(dbRecord(fakeFolder, "case6-rename")._type == ItemTypeFile);
}
+ void testCreateFileWithTrailingSpaces_localAndRemoteTrimmedDoNotExist_renameAndUploadFile()
+ {
+ FakeFolder fakeFolder{ FileInfo() };
+ setupVfs(fakeFolder);
+ QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+
+ const QString fileWithSpaces1(" foo");
+ const QString fileWithSpaces2(" bar ");
+ const QString fileWithSpaces3("bla ");
+ const QString fileWithSpaces4("A/ foo");
+ const QString fileWithSpaces5("A/ bar ");
+ const QString fileWithSpaces6("A/bla ");
+
+ fakeFolder.localModifier().insert(fileWithSpaces1);
+ fakeFolder.localModifier().insert(fileWithSpaces2);
+ fakeFolder.localModifier().insert(fileWithSpaces3);
+ fakeFolder.localModifier().mkdir("A");
+ fakeFolder.localModifier().insert(fileWithSpaces4);
+ fakeFolder.localModifier().insert(fileWithSpaces5);
+ fakeFolder.localModifier().insert(fileWithSpaces6);
+
+ QVERIFY(fakeFolder.syncOnce());
+
+ QVERIFY(fakeFolder.currentLocalState().find(fileWithSpaces1.trimmed()));
+ QVERIFY(!fakeFolder.currentLocalState().find(fileWithSpaces1));
+
+ QVERIFY(fakeFolder.currentLocalState().find(fileWithSpaces2.trimmed()));
+ QVERIFY(!fakeFolder.currentLocalState().find(fileWithSpaces2));
+
+ QVERIFY(fakeFolder.currentLocalState().find(fileWithSpaces3.trimmed()));
+ QVERIFY(!fakeFolder.currentLocalState().find(fileWithSpaces3));
+
+ QVERIFY(fakeFolder.currentLocalState().find("A/foo"));
+ QVERIFY(!fakeFolder.currentLocalState().find(fileWithSpaces4));
+
+ QVERIFY(fakeFolder.currentLocalState().find("A/bar"));
+ QVERIFY(!fakeFolder.currentLocalState().find(fileWithSpaces5));
+
+ QVERIFY(fakeFolder.currentLocalState().find("A/bla"));
+ QVERIFY(!fakeFolder.currentLocalState().find(fileWithSpaces6));
+
+ QVERIFY(fakeFolder.syncOnce());
+
+ QVERIFY(fakeFolder.currentRemoteState().find(fileWithSpaces1.trimmed()));
+ QVERIFY(!fakeFolder.currentRemoteState().find(fileWithSpaces1));
+ QVERIFY(fakeFolder.currentLocalState().find(fileWithSpaces1.trimmed()));
+ QVERIFY(!fakeFolder.currentLocalState().find(fileWithSpaces1));
+
+ QVERIFY(fakeFolder.currentRemoteState().find(fileWithSpaces2.trimmed()));
+ QVERIFY(!fakeFolder.currentRemoteState().find(fileWithSpaces2));
+ QVERIFY(fakeFolder.currentLocalState().find(fileWithSpaces2.trimmed()));
+ QVERIFY(!fakeFolder.currentLocalState().find(fileWithSpaces2));
+
+ QVERIFY(fakeFolder.currentRemoteState().find(fileWithSpaces3.trimmed()));
+ QVERIFY(!fakeFolder.currentRemoteState().find(fileWithSpaces3));
+ QVERIFY(fakeFolder.currentLocalState().find(fileWithSpaces3.trimmed()));
+ QVERIFY(!fakeFolder.currentLocalState().find(fileWithSpaces3));
+
+ QVERIFY(fakeFolder.currentRemoteState().find("A/foo"));
+ QVERIFY(!fakeFolder.currentRemoteState().find(fileWithSpaces4));
+ QVERIFY(fakeFolder.currentLocalState().find("A/foo"));
+ QVERIFY(!fakeFolder.currentLocalState().find(fileWithSpaces4));
+
+ QVERIFY(fakeFolder.currentRemoteState().find("A/bar"));
+ QVERIFY(!fakeFolder.currentRemoteState().find(fileWithSpaces5));
+ QVERIFY(fakeFolder.currentLocalState().find("A/bar"));
+ QVERIFY(!fakeFolder.currentLocalState().find(fileWithSpaces5));
+
+ QVERIFY(fakeFolder.currentRemoteState().find("A/bla"));
+ QVERIFY(!fakeFolder.currentRemoteState().find(fileWithSpaces6));
+ QVERIFY(fakeFolder.currentLocalState().find("A/bla"));
+ QVERIFY(!fakeFolder.currentLocalState().find(fileWithSpaces6));
+ }
+
+ void testCreateFileWithTrailingSpaces_localAndRemoteTrimmedDoNotExist_renameFile()
+ {
+ FakeFolder fakeFolder{ FileInfo() };
+ setupVfs(fakeFolder);
+ QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+ const QString fileWithSpaces4("A/ foo");
+ const QString fileWithSpaces5("A/ bar ");
+ const QString fileWithSpaces6("A/bla ");
+
+ fakeFolder.remoteModifier().mkdir("A");
+ fakeFolder.remoteModifier().insert(fileWithSpaces4);
+ fakeFolder.remoteModifier().insert(fileWithSpaces5);
+ fakeFolder.remoteModifier().insert(fileWithSpaces6);
+
+ QVERIFY(fakeFolder.syncOnce());
+
+ QVERIFY(fakeFolder.currentRemoteState().find("A/foo"));
+ QVERIFY(!fakeFolder.currentRemoteState().find(fileWithSpaces4));
+
+ QVERIFY(fakeFolder.currentRemoteState().find("A/bar"));
+ QVERIFY(!fakeFolder.currentRemoteState().find(fileWithSpaces5));
+
+ QVERIFY(fakeFolder.currentRemoteState().find("A/bla"));
+ QVERIFY(!fakeFolder.currentRemoteState().find(fileWithSpaces6));
+
+ QVERIFY(fakeFolder.syncOnce());
+
+ QVERIFY(fakeFolder.currentRemoteState().find("A/foo"));
+ QVERIFY(!fakeFolder.currentRemoteState().find(fileWithSpaces4));
+ QVERIFY(fakeFolder.currentLocalState().find("A/foo" DVSUFFIX));
+ QVERIFY(!fakeFolder.currentLocalState().find(QString{fileWithSpaces4 + DVSUFFIX}));
+
+ QVERIFY(fakeFolder.currentRemoteState().find("A/bar"));
+ QVERIFY(!fakeFolder.currentRemoteState().find(fileWithSpaces5));
+ QVERIFY(fakeFolder.currentLocalState().find("A/bar" DVSUFFIX));
+ QVERIFY(!fakeFolder.currentLocalState().find(QString{fileWithSpaces5 + DVSUFFIX}));
+
+ QVERIFY(fakeFolder.currentRemoteState().find("A/bla"));
+ QVERIFY(!fakeFolder.currentRemoteState().find(fileWithSpaces6));
+ QVERIFY(fakeFolder.currentLocalState().find("A/bla" DVSUFFIX));
+ QVERIFY(!fakeFolder.currentLocalState().find(QString{fileWithSpaces6 + DVSUFFIX}));
+ }
+
// Dehydration via sync works
void testSyncDehydration()
{