mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-28 19:58:56 +03:00
fix behavior of folder rename with deep hierarchy inside it
propagate renaming of parent folders to child recursively Signed-off-by: Matthieu Gallien <matthieu.gallien@nextcloud.com>
This commit is contained in:
parent
8fa727e299
commit
9a2f07d53b
2 changed files with 74 additions and 11 deletions
|
@ -211,16 +211,26 @@ void PropagateLocalMkdir::startLocalMkdir()
|
|||
done(resultStatus);
|
||||
}
|
||||
|
||||
PropagateLocalRename::PropagateLocalRename(OwncloudPropagator *propagator, const SyncFileItemPtr &item)
|
||||
: PropagateItemJob(propagator, item)
|
||||
{
|
||||
qCDebug(lcPropagateLocalRename) << _item->_file << _item->_renameTarget << _item->_originalFile;
|
||||
}
|
||||
|
||||
void PropagateLocalRename::start()
|
||||
{
|
||||
if (propagator()->_abortRequested)
|
||||
return;
|
||||
|
||||
QString existingFile = propagator()->fullLocalPath(propagator()->adjustRenamedPath(_item->_file));
|
||||
QString targetFile = propagator()->fullLocalPath(_item->_renameTarget);
|
||||
const auto previousNameInDb = propagator()->adjustRenamedPath(_item->_file);
|
||||
const auto existingFile = propagator()->fullLocalPath(propagator()->adjustRenamedPath(_item->_file));
|
||||
const auto targetFile = propagator()->fullLocalPath(_item->_renameTarget);
|
||||
|
||||
const auto fileAlreadyMoved = !QFileInfo::exists(propagator()->fullLocalPath(_item->_originalFile));
|
||||
|
||||
// if the file is a file underneath a moved dir, the _item->file is equal
|
||||
// to _item->renameTarget and the file is not moved as a result.
|
||||
qCDebug(lcPropagateLocalRename) << _item->_file << _item->_renameTarget << _item->_originalFile << previousNameInDb << (fileAlreadyMoved ? "original file has already moved" : "original file is still there");
|
||||
if (_item->_file != _item->_renameTarget) {
|
||||
propagator()->reportProgress(*_item, 0);
|
||||
qCDebug(lcPropagateLocalRename) << "MOVE " << existingFile << " => " << targetFile;
|
||||
|
@ -249,15 +259,37 @@ void PropagateLocalRename::start()
|
|||
}
|
||||
|
||||
SyncJournalFileRecord oldRecord;
|
||||
if (!propagator()->_journal->getFileRecord(_item->_originalFile, &oldRecord)) {
|
||||
if (!propagator()->_journal->getFileRecord(fileAlreadyMoved ? previousNameInDb : _item->_originalFile, &oldRecord)) {
|
||||
qCWarning(lcPropagateLocalRename) << "could not get file from local DB" << _item->_originalFile;
|
||||
done(SyncFileItem::NormalError, tr("could not get file %1 from local DB").arg(_item->_originalFile));
|
||||
return;
|
||||
}
|
||||
if (!propagator()->_journal->deleteFileRecord(_item->_originalFile)) {
|
||||
qCWarning(lcPropagateLocalRename) << "could not delete file from local DB" << _item->_originalFile;
|
||||
done(SyncFileItem::NormalError, tr("Could not delete file record %1 from local DB").arg(_item->_originalFile));
|
||||
return;
|
||||
|
||||
const auto deleteOldRecord = [this] (const QString &fileName) -> bool
|
||||
{
|
||||
SyncJournalFileRecord oldRecord;
|
||||
if (!propagator()->_journal->getFileRecord(fileName, &oldRecord)) {
|
||||
qCWarning(lcPropagateLocalRename) << "could not get file from local DB" << fileName;
|
||||
done(SyncFileItem::NormalError, tr("could not get file %1 from local DB").arg(fileName));
|
||||
return false;
|
||||
}
|
||||
if (!propagator()->_journal->deleteFileRecord(fileName)) {
|
||||
qCWarning(lcPropagateLocalRename) << "could not delete file from local DB" << fileName;
|
||||
done(SyncFileItem::NormalError, tr("Could not delete file record %1 from local DB").arg(fileName));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
if (fileAlreadyMoved) {
|
||||
if (!deleteOldRecord(previousNameInDb)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!deleteOldRecord(_item->_originalFile)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto &vfs = propagator()->syncOptions()._vfs;
|
||||
|
@ -282,6 +314,40 @@ void PropagateLocalRename::start()
|
|||
return;
|
||||
}
|
||||
} else {
|
||||
auto dbQueryResult = propagator()->_journal->getFilesBelowPath(oldFile.toUtf8(), [oldFile, this] (const SyncJournalFileRecord &record) -> void {
|
||||
const auto oldFileName = record._path;
|
||||
const auto oldFileNameString = QString::fromUtf8(oldFileName);
|
||||
auto newFileNameString = oldFileNameString;
|
||||
newFileNameString.replace(0, oldFile.length(), _item->_renameTarget);
|
||||
|
||||
if (oldFileNameString == newFileNameString) {
|
||||
return;
|
||||
}
|
||||
|
||||
SyncJournalFileRecord oldRecord;
|
||||
if (!propagator()->_journal->getFileRecord(oldFileName, &oldRecord)) {
|
||||
qCWarning(lcPropagateLocalRename) << "could not get file from local DB" << oldFileName;
|
||||
done(SyncFileItem::NormalError, tr("could not get file %1 from local DB").arg(oldFileNameString));
|
||||
return;
|
||||
}
|
||||
if (!propagator()->_journal->deleteFileRecord(oldFileName)) {
|
||||
qCWarning(lcPropagateLocalRename) << "could not delete file from local DB" << oldFileName;
|
||||
done(SyncFileItem::NormalError, tr("Could not delete file record %1 from local DB").arg(oldFileNameString));
|
||||
return;
|
||||
}
|
||||
|
||||
auto newItem = SyncFileItem::fromSyncJournalFileRecord(oldRecord);
|
||||
newItem->_file = newFileNameString;
|
||||
const auto result = propagator()->updateMetadata(*newItem);
|
||||
if (!result) {
|
||||
done(SyncFileItem::FatalError, tr("Error updating metadata: %1").arg(result.error()));
|
||||
return;
|
||||
}
|
||||
});
|
||||
if (!dbQueryResult) {
|
||||
done(SyncFileItem::FatalError, tr("Failed to propagate directory rename in hierarchy"));
|
||||
return;
|
||||
}
|
||||
propagator()->_renamedDirectories.insert(oldFile, _item->_renameTarget);
|
||||
if (!PropagateRemoteMove::adjustSelectiveSync(propagator()->_journal, oldFile, _item->_renameTarget)) {
|
||||
done(SyncFileItem::FatalError, tr("Failed to rename file"));
|
||||
|
|
|
@ -86,10 +86,7 @@ class PropagateLocalRename : public PropagateItemJob
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
PropagateLocalRename(OwncloudPropagator *propagator, const SyncFileItemPtr &item)
|
||||
: PropagateItemJob(propagator, item)
|
||||
{
|
||||
}
|
||||
PropagateLocalRename(OwncloudPropagator *propagator, const SyncFileItemPtr &item);
|
||||
void start() override;
|
||||
JobParallelism parallelism() override { return _item->isDirectory() ? WaitForFinished : FullParallelism; }
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue