mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-26 06:55:59 +03:00
clean transition when files with spaces exist already
Signed-off-by: Matthieu Gallien <matthieu.gallien@nextcloud.com>
This commit is contained in:
parent
e89268bdd7
commit
8decd475e5
3 changed files with 73 additions and 39 deletions
|
@ -52,10 +52,10 @@ bool ProcessDirectoryJob::checkForInvalidFileName(const PathTuple &path,
|
|||
if (entriesIter != entries.end()) {
|
||||
QString errorMessage;
|
||||
const auto newFileNameEntry = entriesIter->second;
|
||||
if (newFileNameEntry.serverEntry.isValid()) {
|
||||
if (entry.serverEntry.isValid() && newFileNameEntry.serverEntry.isValid()) {
|
||||
errorMessage = tr("File contains trailing spaces and could not be renamed, because a file with the same name already exists on the server.");
|
||||
}
|
||||
if (newFileNameEntry.localEntry.isValid()) {
|
||||
if (entry.localEntry.isValid() && newFileNameEntry.localEntry.isValid()) {
|
||||
errorMessage = tr("File contains trailing spaces and could not be renamed, because a file with the same name already exists locally.");
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@ bool ProcessDirectoryJob::checkForInvalidFileName(const PathTuple &path,
|
|||
item->_instruction = CSYNC_INSTRUCTION_ERROR;
|
||||
item->_status = SyncFileItem::NormalError;
|
||||
item->_errorString = errorMessage;
|
||||
emit _discoveryData->itemDiscovered(item);
|
||||
processFileFinalize(item, path, false, ParentNotChanged, ParentNotChanged);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -852,6 +852,39 @@ void ProcessDirectoryJob::processFileAnalyzeLocalInfo(
|
|||
processFileFinalize(item, path, recurse, recurseQueryLocal, recurseQueryServer);
|
||||
};
|
||||
|
||||
auto handleInvalidSpaceRename = [&] (SyncFileItem::Direction direction) {
|
||||
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 = direction;
|
||||
item->_fileId = base._fileId;
|
||||
item->_remotePerm = base._remotePerm;
|
||||
item->_etag = base._etag;
|
||||
item->_type = base._type;
|
||||
};
|
||||
|
||||
if (!localEntry.isValid()) {
|
||||
if (_queryLocal == ParentNotChanged && dbEntry.isValid()) {
|
||||
// Not modified locally (ParentNotChanged)
|
||||
|
@ -933,6 +966,8 @@ void ProcessDirectoryJob::processFileAnalyzeLocalInfo(
|
|||
|| _discoveryData->_syncOptions._vfs->needsMetadataUpdate(*item))) {
|
||||
item->_instruction = CSYNC_INSTRUCTION_UPDATE_METADATA;
|
||||
item->_direction = SyncFileItem::Down;
|
||||
} else if (!localEntry.renameName.isEmpty()) {
|
||||
handleInvalidSpaceRename(SyncFileItem::Up);
|
||||
}
|
||||
} else if (!typeChange && isVfsWithSuffix()
|
||||
&& dbEntry.isVirtualFile() && !localEntry.isVirtualFile
|
||||
|
@ -1019,37 +1054,7 @@ void ProcessDirectoryJob::processFileAnalyzeLocalInfo(
|
|||
}
|
||||
|
||||
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;
|
||||
|
||||
handleInvalidSpaceRename(SyncFileItem::Down);
|
||||
finalize();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -238,10 +238,14 @@ void PropagateRemoteMove::finalize()
|
|||
auto &vfs = propagator()->syncOptions()._vfs;
|
||||
auto pinState = vfs->pinState(_item->_originalFile);
|
||||
|
||||
// Delete old db data.
|
||||
propagator()->_journal->deleteFileRecord(_item->_originalFile);
|
||||
if (!vfs->setPinState(_item->_originalFile, PinState::Inherited)) {
|
||||
qCWarning(lcPropagateRemoteMove) << "Could not set pin state of" << _item->_originalFile << "to inherited";
|
||||
const auto targetFile = propagator()->fullLocalPath(_item->_renameTarget);
|
||||
|
||||
if (QFileInfo::exists(targetFile)) {
|
||||
// Delete old db data.
|
||||
propagator()->_journal->deleteFileRecord(_item->_originalFile);
|
||||
if (!vfs->setPinState(_item->_originalFile, PinState::Inherited)) {
|
||||
qCWarning(lcPropagateRemoteMove) << "Could not set pin state of" << _item->_originalFile << "to inherited";
|
||||
}
|
||||
}
|
||||
|
||||
SyncFileItem newItem(*_item);
|
||||
|
@ -256,7 +260,6 @@ void PropagateRemoteMove::finalize()
|
|||
}
|
||||
}
|
||||
|
||||
const auto targetFile = propagator()->fullLocalPath(_item->_renameTarget);
|
||||
if (!QFileInfo::exists(targetFile)) {
|
||||
propagator()->_journal->commit("Remote Rename");
|
||||
done(SyncFileItem::Success);
|
||||
|
|
|
@ -360,6 +360,32 @@ private slots:
|
|||
QVERIFY(fakeFolder.currentLocalState().find(fileWithSpaces));
|
||||
QVERIFY(fakeFolder.currentLocalState().find(fileTrimmed));
|
||||
}
|
||||
|
||||
void testCreateFileWithTrailingSpaces_localAndRemoteTrimmedExists_renameFile()
|
||||
{
|
||||
FakeFolder fakeFolder{FileInfo{}};
|
||||
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
|
||||
const QString fileWithSpaces1(" foo");
|
||||
const QString fileWithSpaces2(" bar ");
|
||||
const QString fileWithSpaces3("bla ");
|
||||
|
||||
fakeFolder.localModifier().insert(fileWithSpaces1);
|
||||
fakeFolder.localModifier().insert(fileWithSpaces2);
|
||||
fakeFolder.localModifier().insert(fileWithSpaces3);
|
||||
fakeFolder.remoteModifier().insert(fileWithSpaces1);
|
||||
fakeFolder.remoteModifier().insert(fileWithSpaces2);
|
||||
fakeFolder.remoteModifier().insert(fileWithSpaces3);
|
||||
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
|
||||
QVERIFY(fakeFolder.syncOnce());
|
||||
|
||||
auto expectedState = fakeFolder.currentLocalState();
|
||||
qDebug() << expectedState;
|
||||
QCOMPARE(fakeFolder.currentRemoteState(), expectedState);
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_GUILESS_MAIN(TestLocalDiscovery)
|
||||
|
|
Loading…
Reference in a new issue