connect(_engine.data(), &SyncEngine::aboutToRemoveAllFiles,
this, &Folder::slotAboutToRemoveAllFiles);
+ connect(_engine.data(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders,
+ this, &Folder::slotNeedToRemoveRemnantsReadOnlyFolders);
connect(_engine.data(), &SyncEngine::transmissionProgress, this, &Folder::slotTransmissionProgress);
connect(_engine.data(), &SyncEngine::itemCompleted,
this, &Folder::slotItemCompleted);
msgBox->open();
}
+void Folder::slotNeedToRemoveRemnantsReadOnlyFolders(const QList<SyncFileItemPtr> &folders,
+ const QString &localPath,
+ std::function<void (bool)> callback)
+{
+ const auto msg = tr("Do you want to clean up remnant read-only folders left over from previous failed synchronization attempts.");
+ auto msgBox = new QMessageBox(QMessageBox::Question, tr("Remove remnant invalid folders?"),
+ msg, QMessageBox::NoButton);
+ msgBox->setAttribute(Qt::WA_DeleteOnClose);
+ msgBox->setWindowFlags(msgBox->windowFlags() | Qt::WindowStaysOnTopHint);
+ msgBox->addButton(tr("Proceed to remove remnant folders"), QMessageBox::AcceptRole);
+ const auto keepBtn = msgBox->addButton(tr("Do nothing"), QMessageBox::RejectRole);
+ setSyncPaused(true);
+ connect(msgBox, &QMessageBox::finished, this, [msgBox, keepBtn, callback, folders, localPath, this] {
+ const bool cancel = msgBox->clickedButton() == keepBtn;
+ if (!cancel) {
+ for(const auto &oneFolder : folders) {
+ FileSystem::removeRecursively(localPath + oneFolder->_file);
+ }
+ }
+ callback(cancel);
+ if (cancel) {
+ setSyncPaused(true);
+ }
+ });
+ connect(this, &Folder::destroyed, msgBox, &QMessageBox::deleteLater);
+ msgBox->open();
+}
+
void Folder::removeLocalE2eFiles()
{
qCDebug(lcFolder) << "Removing local E2EE files";
bool itemInstruction(const ItemCompletedSpy &spy, const QString &path, const SyncInstructions instr)
{
auto item = spy.findItem(path);
+ const auto checkHelper = [item, instr]() {
+ QCOMPARE(item->_instruction, instr);
+ };
+
+ checkHelper();
return item->_instruction == instr;
}
bool discoveryInstruction(const SyncFileItemVector &spy, const QString &path, const SyncInstructions instr)
{
auto item = findDiscoveryItem(spy, path);
+ const auto checkHelper = [item, instr]() {
+ QCOMPARE(item->_instruction, instr);
+ };
+
+ checkHelper();
return item->_instruction == instr;
}
FakeFolder fakeFolder{ FileInfo() };
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+ QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders,
+ [&](const QList<SyncFileItemPtr> &folders, const QString &localPath, std::function<void(bool)> callback) {
+ qDebug() << "aboutToRemoveRemnantsReadOnlyFolders called";
+ Q_UNUSED(folders);
+ Q_UNUSED(localPath);
+ callback(false);
+ });
+
// Some of this test depends on the order of discovery. With threading
// that order becomes effectively random, but we want to make sure to test
// all cases and thus disable threading.
{
FakeFolder fakeFolder{FileInfo{}};
+ QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders,
+ [&](const QList<SyncFileItemPtr> &folders, const QString &localPath, std::function<void(bool)> callback) {
+ Q_UNUSED(folders)
+ Q_UNUSED(localPath)
+ callback(false);
+ });
+
// Some of this test depends on the order of discovery. With threading
// that order becomes effectively random, but we want to make sure to test
// all cases and thus disable threading.
void testAllowedMoveForbiddenDelete() {
FakeFolder fakeFolder{FileInfo{}};
+ QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders,
+ [&](const QList<SyncFileItemPtr> &folders, const QString &localPath, std::function<void(bool)> callback) {
+ for(const auto &oneFolder : folders) {
+ FileSystem::removeRecursively(localPath + oneFolder->_file);
+ }
+ callback(false);
+ });
+
// Some of this test depends on the order of discovery. With threading
// that order becomes effectively random, but we want to make sure to test
// all cases and thus disable threading.
void testParentMoveNotAllowedChildrenRestored()
{
FakeFolder fakeFolder{FileInfo{}};
+
+ QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders,
+ [&](const QList<SyncFileItemPtr> &folders, const QString &localPath, std::function<void(bool)> callback) {
+ for(const auto &oneFolder : folders) {
+ FileSystem::removeRecursively(localPath + oneFolder->_file);
+ }
+ callback(false);
+ });
+
auto &lm = fakeFolder.localModifier();
auto &rm = fakeFolder.remoteModifier();
rm.mkdir("forbidden-move");
{
FakeFolder fakeFolder{FileInfo{}};
+ QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders,
+ [&](const QList<SyncFileItemPtr> &folders, const QString &localPath, std::function<void(bool)> callback) {
+ for(const auto &oneFolder : folders) {
+ FileSystem::removeRecursively(localPath + oneFolder->_file);
+ }
+ callback(false);
+ });
+
auto &remote = fakeFolder.remoteModifier();
remote.mkdir("readOnlyFolder");
{
FakeFolder fakeFolder{FileInfo{}};
+ QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders,
+ [&](const QList<SyncFileItemPtr> &folders, const QString &localPath, std::function<void(bool)> callback) {
+ for(const auto &oneFolder : folders) {
+ FileSystem::removeRecursively(localPath + oneFolder->_file);
+ }
+ callback(false);
+ });
+
auto &remote = fakeFolder.remoteModifier();
remote.mkdir("readWriteFolder");
{
FakeFolder fakeFolder{FileInfo{}};
+ QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders,
+ [&](const QList<SyncFileItemPtr> &folders, const QString &localPath, std::function<void(bool)> callback) {
+ for(const auto &oneFolder : folders) {
+ FileSystem::removeRecursively(localPath + oneFolder->_file);
+ }
+ callback(false);
+ });
+
auto &remote = fakeFolder.remoteModifier();
remote.mkdir("testFolder");
{
FakeFolder fakeFolder{FileInfo{}};
+ QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders,
+ [&](const QList<SyncFileItemPtr> &folders, const QString &localPath, std::function<void(bool)> callback) {
+ for(const auto &oneFolder : folders) {
+ FileSystem::removeRecursively(localPath + oneFolder->_file);
+ }
+ callback(false);
+ });
+
auto &remote = fakeFolder.remoteModifier();
remote.mkdir("testFolder");
{
FakeFolder fakeFolder{FileInfo{}};
+ QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders,
+ [&](const QList<SyncFileItemPtr> &folders, const QString &localPath, std::function<void(bool)> callback) {
+ for(const auto &oneFolder : folders) {
+ FileSystem::removeRecursively(localPath + oneFolder->_file);
+ }
+ callback(false);
+ });
+
auto &remote = fakeFolder.remoteModifier();
remote.mkdir("readOnlyFolder");
{
FakeFolder fakeFolder{FileInfo{}};
+ QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders,
+ [&](const QList<SyncFileItemPtr> &folders, const QString &localPath, std::function<void(bool)> callback) {
+ for(const auto &oneFolder : folders) {
+ FileSystem::removeRecursively(localPath + oneFolder->_file);
+ }
+ callback(false);
+ });
+
auto &remote = fakeFolder.remoteModifier();
remote.mkdir("readOnlyFolder");
{
FakeFolder fakeFolder{FileInfo{}};
+ QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders,
+ [&](const QList<SyncFileItemPtr> &folders, const QString &localPath, std::function<void(bool)> callback) {
+ for(const auto &oneFolder : folders) {
+ FileSystem::removeRecursively(localPath + oneFolder->_file);
+ }
+ callback(false);
+ });
+
auto &remote = fakeFolder.remoteModifier();
remote.mkdir("readOnlyFolder");
{
FakeFolder fakeFolder{FileInfo{}};
+ QObject::connect(&fakeFolder.syncEngine(), &SyncEngine::aboutToRemoveRemnantsReadOnlyFolders,
+ [&](const QList<SyncFileItemPtr> &folders, const QString &localPath, std::function<void(bool)> callback) {
+ for(const auto &oneFolder : folders) {
+ FileSystem::removeRecursively(localPath + oneFolder->_file);
+ }
+ callback(false);
+ });
+
auto &remote = fakeFolder.remoteModifier();
remote.mkdir("readOnlyFolder");