<< " | fileid: " << dbEntry._fileId << "//" << serverEntry.fileId
<< " | inode: " << dbEntry._inode << "/" << localEntry.inode << "/";
- if (_discoveryData->_renamedItems.contains(path._original)) {
+ if (_discoveryData->isRenamed(path._original)) {
qCDebug(lcDisco) << "Ignoring renamed";
return; // Ignore this.
}
// Now we know there is a sane rename candidate.
QString originalPath = QString::fromUtf8(base._path);
- if (_discoveryData->_renamedItems.contains(originalPath)) {
+ if (_discoveryData->isRenamed(originalPath)) {
qCInfo(lcDisco, "folder already has a rename entry, skipping");
return;
}
bool wasDeletedOnServer = _discoveryData->findAndCancelDeletedJob(originalPath).first;
auto postProcessRename = [this, item, base, originalPath](PathTuple &path) {
- auto adjustedOriginalPath = _discoveryData->adjustRenamedPath(originalPath);
- _discoveryData->_renamedItems.insert(originalPath, path._target);
+ auto adjustedOriginalPath = _discoveryData->adjustRenamedPath(originalPath, SyncFileItem::Up);
+ _discoveryData->_renamedItemsRemote.insert(originalPath, path._target);
item->_modtime = base._modtime;
item->_inode = base._inode;
item->_instruction = CSYNC_INSTRUCTION_RENAME;
QTimer::singleShot(0, _discoveryData, &DiscoveryPhase::scheduleMoreJobs);
if (etag || etag.error().code != 404 ||
// Somehow another item claimed this original path, consider as if it existed
- _discoveryData->_renamedItems.contains(originalPath)) {
+ _discoveryData->isRenamed(originalPath)) {
// If the file exist or if there is another error, consider it is a new file.
postProcessServerNew();
return;
}
}
auto originalPath = QString::fromUtf8(base._path);
- if (isMove && _discoveryData->_renamedItems.contains(originalPath))
+ if (isMove && _discoveryData->isRenamed(originalPath))
isMove = false;
//Check local permission if we are allowed to put move the file here
auto wasDeletedOnClient = _discoveryData->findAndCancelDeletedJob(originalPath);
auto processRename = [item, originalPath, base, this](PathTuple &path) {
- auto adjustedOriginalPath = _discoveryData->adjustRenamedPath(originalPath);
- _discoveryData->_renamedItems.insert(originalPath, path._target);
+ auto adjustedOriginalPath = _discoveryData->adjustRenamedPath(originalPath, SyncFileItem::Down);
+ _discoveryData->_renamedItemsLocal.insert(originalPath, path._target);
item->_renameTarget = path._target;
path._server = adjustedOriginalPath;
item->_file = path._server;
chopVirtualFileSuffix(serverOriginalPath);
auto job = new RequestEtagJob(_discoveryData->_account, serverOriginalPath, this);
connect(job, &RequestEtagJob::finishedWithResult, this, [=](const HttpResult<QString> &etag) mutable {
- if (!etag || (*etag != base._etag && !item->isDirectory()) || _discoveryData->_renamedItems.contains(originalPath)) {
+ if (!etag || (*etag != base._etag && !item->isDirectory()) || _discoveryData->isRenamed(originalPath)) {
qCInfo(lcDisco) << "Can't rename because the etag has changed or the directory is gone" << originalPath;
// Can't be a rename, leave it as a new.
postProcessLocalNew();
propfindJob->start();
}
-
/* Given a path on the remote, give the path as it is when the rename is done */
-QString DiscoveryPhase::adjustRenamedPath(const QString &original) const
+QString DiscoveryPhase::adjustRenamedPath(const QString &original, SyncFileItem::Direction d) const
{
- return OCC::adjustRenamedPath(_renamedItems, original);
+ return OCC::adjustRenamedPath(d == SyncFileItem::Down ? _renamedItemsRemote : _renamedItemsLocal, original);
}
QString adjustRenamedPath(const QMap<QString, QString> renamedItems, const QString original)
friend class ProcessDirectoryJob;
QMap<QString, SyncFileItemPtr> _deletedItem;
QMap<QString, ProcessDirectoryJob *> _queuedDeletedDirectories;
- QMap<QString, QString> _renamedItems; // map source -> destinations
+ // map source -> destinations
+ QMap<QString, QString> _renamedItemsRemote;
+ QMap<QString, QString> _renamedItemsLocal;
+ bool isRenamed(const QString &p) { return _renamedItemsLocal.contains(p) || _renamedItemsRemote.contains(p); }
int _currentlyActiveJobs = 0;
// both must contain a sorted list
* Note that it only considers parent directory renames. So if A/B got renamed to C/D,
* checking A/B/file would yield C/D/file, but checking A/B would yield A/B.
*/
- QString adjustRenamedPath(const QString &original) const;
+ QString adjustRenamedPath(const QString &original, SyncFileItem::Direction) const;
/**
* Check if there is already a job to delete that item.
QCOMPARE(fakeFolder.currentLocalState(), expectedState);
QCOMPARE(fakeFolder.currentRemoteState(), expectedState);
}
+
+ void testDeepHierarchy_data()
+ {
+ QTest::addColumn<bool>("local");
+ QTest::newRow("remote") << false;
+ QTest::newRow("local") << true;
+ }
+
+ void testDeepHierarchy()
+ {
+ QFETCH(bool, local);
+ FakeFolder fakeFolder { FileInfo::A12_B12_C12_S12() };
+ auto &modifier = local ? fakeFolder.localModifier() : fakeFolder.remoteModifier();
+
+ modifier.mkdir("FolA");
+ modifier.mkdir("FolA/FolB");
+ modifier.mkdir("FolA/FolB/FolC");
+ modifier.mkdir("FolA/FolB/FolC/FolD");
+ modifier.mkdir("FolA/FolB/FolC/FolD/FolE");
+ modifier.insert("FolA/FileA.txt");
+ modifier.insert("FolA/FolB/FileB.txt");
+ modifier.insert("FolA/FolB/FolC/FileC.txt");
+ modifier.insert("FolA/FolB/FolC/FolD/FileD.txt");
+ modifier.insert("FolA/FolB/FolC/FolD/FolE/FileE.txt");
+ QVERIFY(fakeFolder.syncOnce());
+
+ modifier.insert("FolA/FileA2.txt");
+ modifier.insert("FolA/FolB/FileB2.txt");
+ modifier.insert("FolA/FolB/FolC/FileC2.txt");
+ modifier.insert("FolA/FolB/FolC/FolD/FileD2.txt");
+ modifier.insert("FolA/FolB/FolC/FolD/FolE/FileE2.txt");
+ modifier.rename("FolA", "FolA_Renamed");
+ modifier.rename("FolA_Renamed/FolB", "FolB_Renamed");
+ modifier.rename("FolB_Renamed/FolC", "FolA");
+ modifier.rename("FolA/FolD", "FolA/FolD_Renamed");
+ modifier.mkdir("FolB_Renamed/New");
+ modifier.rename("FolA/FolD_Renamed/FolE", "FolB_Renamed/New/FolE");
+ auto expected = local ? fakeFolder.currentLocalState() : fakeFolder.currentRemoteState();
+ QVERIFY(fakeFolder.syncOnce());
+ QCOMPARE(fakeFolder.currentLocalState(), expected);
+ QCOMPARE(fakeFolder.currentRemoteState(), expected);
+ }
};
QTEST_GUILESS_MAIN(TestSyncMove)