Do not remove a folder that has files that were not uploaded yet during propagation.
authoralex-z <blackslayer4@gmail.com>
Fri, 11 Feb 2022 17:22:40 +0000 (19:22 +0200)
committerMatthieu Gallien (Rebase PR Action) <matthieu_gallien@yahoo.fr>
Fri, 25 Feb 2022 15:31:26 +0000 (15:31 +0000)
Signed-off-by: alex-z <blackslayer4@gmail.com>
src/libsync/owncloudpropagator.cpp
src/libsync/owncloudpropagator.h

index c555976462befa48cd2cdb14a9100ec1591e426c..de5fcbe89ef69478276c556690bdd4d3c7ad8174 100644 (file)
@@ -413,6 +413,64 @@ void OwncloudPropagator::resetDelayedUploadTasks()
     _delayedTasks.clear();
 }
 
+void OwncloudPropagator::adjustDeletedFoldersWithNewChildren(SyncFileItemVector &items)
+{
+    /* 
+       process each item that is new and is a directory and make sure every parent in its tree has the instruction CSYNC_INSTRUCTION_NEW
+       instead of CSYNC_INSTRUCTION_REMOVE 
+    */
+    for (const auto &item : items) {
+        if (item->_instruction != CSYNC_INSTRUCTION_NEW || item->_direction != SyncFileItem::Up || !item->isDirectory() || item->_file == QStringLiteral("/")) {
+            continue;
+        }
+
+        // #1 get root folder name for the current item that we need to reupload
+        const auto folderPathSplit = item->_file.split(QLatin1Char('/'), Qt::SkipEmptyParts);
+        if (folderPathSplit.isEmpty()) {
+            continue;
+        }
+        const auto itemRootFolderName = folderPathSplit.first();
+        if (itemRootFolderName.isEmpty()) {
+            continue;
+        }
+        // #2 iterate backwords (for optimization) and find the root folder by name
+        const auto itemRootFolderReverseIt = std::find_if(std::rbegin(items), std::rend(items), [&itemRootFolderName](const auto &currentItem) {
+            return currentItem->_file == itemRootFolderName;
+        });
+
+        if (itemRootFolderReverseIt == std::rend(items)) {
+            continue;
+        }
+
+        // #3 convert reverse iterator to normal iterator
+        const auto itemFolderIt = (itemRootFolderReverseIt + 1).base();
+
+        // #4 if the root folder is set to be removed, then we will need to fix this by reuploading every folder in
+        // the tree, including the root
+        if (itemFolderIt == std::end(items)) {
+            continue;
+        }
+
+        auto nextFolderInTreeIt = itemFolderIt;
+        do {
+            // #5 Iterate forward from the CSYNC_INSTRUCTION_NEW folder's root, and make sure every folder in it's tree is set to CSYNC_INSTRUCTION_NEW
+            if ((*nextFolderInTreeIt)->isDirectory()
+                && (*nextFolderInTreeIt)->_instruction == CSYNC_INSTRUCTION_REMOVE
+                && (*nextFolderInTreeIt)->_direction == SyncFileItem::Down
+                && item->_file.startsWith(QString((*nextFolderInTreeIt)->_file) + QLatin1Char('/'))) {
+
+                qCWarning(lcPropagator) << "WARNING: New directory to upload " << item->_file
+                    << "is in the removed directories tree " << (*nextFolderInTreeIt)->_file
+                    << " This should not happen! But, we are going to reupload the entire folder structure.";
+
+                (*nextFolderInTreeIt)->_instruction = CSYNC_INSTRUCTION_NEW;
+                (*nextFolderInTreeIt)->_direction = SyncFileItem::Up;
+            }
+            ++nextFolderInTreeIt;
+        } while (nextFolderInTreeIt != std::end(items) && (*nextFolderInTreeIt)->_file != item->_file);
+    }
+}
+
 qint64 OwncloudPropagator::smallFileSize()
 {
     const qint64 smallFileSize = 100 * 1024; //default to 1 MB. Not dynamic right now.
@@ -448,6 +506,9 @@ void OwncloudPropagator::start(SyncFileItemVector &&items)
             items.end());
     }
 
+    // process each item that is new and is a directory and make sure every parent in its tree has the instruction NEW instead of REMOVE
+    adjustDeletedFoldersWithNewChildren(items);
+
     resetDelayedUploadTasks();
     _rootJob.reset(new PropagateRootDirectory(this));
     QStack<QPair<QString /* directory name */, PropagateDirectory * /* job */>> directories;
index 28f3994b0d8f00efad76e739d93883229a539af5..79d017e8283897a46a9016cb2d4fef9b9e7c57a1 100644 (file)
@@ -665,6 +665,8 @@ private:
 
     void resetDelayedUploadTasks();
 
+    static void adjustDeletedFoldersWithNewChildren(SyncFileItemVector &items);
+
     AccountPtr _account;
     QScopedPointer<PropagateRootDirectory> _rootJob;
     SyncOptions _syncOptions;