diff options
author | Olivier Goffart <ogoffart@woboq.com> | 2018-05-28 15:49:02 +0300 |
---|---|---|
committer | Olivier Goffart <olivier@woboq.com> | 2018-05-30 12:57:57 +0300 |
commit | 1753ce651bf7f8fabcbb0d920fcc4ad3fe0bfde2 (patch) | |
tree | ddd78743a8c9c1b727d47911858bb494edb96c09 | |
parent | 104f8c9ba2399fc3d2ff7212e273948b337c7d1f (diff) |
Virtual Files: Allow to download a folder recursively from the socket API
Issue: #6466
-rw-r--r-- | src/common/syncjournaldb.cpp | 19 | ||||
-rw-r--r-- | src/common/syncjournaldb.h | 6 | ||||
-rw-r--r-- | src/gui/folder.cpp | 15 | ||||
-rw-r--r-- | src/gui/folder.h | 3 | ||||
-rw-r--r-- | src/gui/socketapi.cpp | 4 | ||||
-rw-r--r-- | test/testsyncvirtualfiles.cpp | 99 |
6 files changed, 139 insertions, 7 deletions
diff --git a/src/common/syncjournaldb.cpp b/src/common/syncjournaldb.cpp index e052b8502..9054951f7 100644 --- a/src/common/syncjournaldb.cpp +++ b/src/common/syncjournaldb.cpp @@ -1962,6 +1962,25 @@ void SyncJournalDb::clearFileTable() query.exec(); } +void SyncJournalDb::markVirtualFileForDownloadRecursively(const QByteArray &path) +{ + QMutexLocker lock(&_mutex); + if (!checkConnect()) + return; + + static_assert(ItemTypeVirtualFile == 4 && ItemTypeVirtualFileDownload == 5, ""); + SqlQuery query("UPDATE metadata SET type=5 WHERE " IS_PREFIX_PATH_OF("?1", "path") " AND type=4;", _db); + query.bindValue(1, path); + query.exec(); + + // We also must make sure we do not read the files from the database (same logic as in avoidReadFromDbOnNextSync) + // This includes all the parents up to the root, but also all the directory within the selected dir. + static_assert(ItemTypeDirectory == 2, ""); + query.prepare("UPDATE metadata SET md5='_invalid_' WHERE (" IS_PREFIX_PATH_OF("?1", "path") " OR " IS_PREFIX_PATH_OR_EQUAL("path", "?1") ") AND type == 2;"); + query.bindValue(1, path); + query.exec(); +} + void SyncJournalDb::commit(const QString &context, bool startTrans) { QMutexLocker lock(&_mutex); diff --git a/src/common/syncjournaldb.h b/src/common/syncjournaldb.h index 4db859bbe..5931e8d03 100644 --- a/src/common/syncjournaldb.h +++ b/src/common/syncjournaldb.h @@ -245,6 +245,12 @@ public: */ void clearFileTable(); + /** + * Set the 'ItemTypeVirtualFileDownload' to all the files that have the ItemTypeVirtualFile flag + * within the directory specified path path + */ + void markVirtualFileForDownloadRecursively(const QByteArray &path); + private: int getFileRecordCount(); bool updateDatabaseStructure(); diff --git a/src/gui/folder.cpp b/src/gui/folder.cpp index 314e67f12..2e06986f8 100644 --- a/src/gui/folder.cpp +++ b/src/gui/folder.cpp @@ -519,11 +519,16 @@ void Folder::downloadVirtualFile(const QString &_relativepath) _journal.getFileRecord(relativepath, &record); if (!record.isValid()) return; - record._type = ItemTypeVirtualFileDownload; - _journal.setFileRecord(record); - - // Make sure we go over that file during the discovery - _journal.avoidReadFromDbOnNextSync(relativepath); + if (record._type == ItemTypeVirtualFile) { + record._type = ItemTypeVirtualFileDownload; + _journal.setFileRecord(record); + // Make sure we go over that file during the discovery + _journal.avoidReadFromDbOnNextSync(relativepath); + } else if (record._type == ItemTypeDirectory) { + _journal.markVirtualFileForDownloadRecursively(relativepath); + } else { + qCWarning(lcFolder) << "Invalid existing record " << record._type << " for file " << _relativepath; + } // Schedule a sync (Folder man will start the sync in a few ms) slotScheduleThisFolder(); diff --git a/src/gui/folder.h b/src/gui/folder.h index ca6468778..a38bbb928 100644 --- a/src/gui/folder.h +++ b/src/gui/folder.h @@ -242,6 +242,9 @@ public: */ void registerFolderWatcher(); + /** new files are downloaded as virtual files */ + bool useVirtualFiles() { return _definition.useVirtualFiles; } + signals: void syncStateChange(); void syncStarted(); diff --git a/src/gui/socketapi.cpp b/src/gui/socketapi.cpp index fabb65469..43466eb6d 100644 --- a/src/gui/socketapi.cpp +++ b/src/gui/socketapi.cpp @@ -611,7 +611,7 @@ void SocketApi::command_DOWNLOAD_VIRTUAL_FILE(const QString &filesArg, SocketLis auto suffix = QStringLiteral(APPLICATION_DOTVIRTUALFILE_SUFFIX); for (const auto &file : files) { - if (!file.endsWith(suffix)) + if (!file.endsWith(suffix) && !QFileInfo(file).isDir()) continue; QString relativePath; auto folder = FolderMan::instance()->folderForPath(file, &relativePath); @@ -764,7 +764,7 @@ void SocketApi::command_GET_MENU_ITEMS(const QString &argument, OCC::SocketListe auto virtualFileSuffix = QStringLiteral(APPLICATION_DOTVIRTUALFILE_SUFFIX); bool hasVirtualFile = false; for (const auto &file : files) { - if (file.endsWith(virtualFileSuffix)) + if (file.endsWith(virtualFileSuffix) || (folder->useVirtualFiles() && QFileInfo(file).isDir())) hasVirtualFile = true; } if (hasVirtualFile) diff --git a/test/testsyncvirtualfiles.cpp b/test/testsyncvirtualfiles.cpp index 0bcd33c51..db677a306 100644 --- a/test/testsyncvirtualfiles.cpp +++ b/test/testsyncvirtualfiles.cpp @@ -485,6 +485,105 @@ private slots: QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); QVERIFY(!dbRecord(fakeFolder, "A/a1.owncloud").isValid()); } + + void testDownloadRecursive() + { + FakeFolder fakeFolder{ FileInfo() }; + SyncOptions syncOptions; + syncOptions._newFilesAreVirtual = true; + fakeFolder.syncEngine().setSyncOptions(syncOptions); + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + + // Create a virtual file for remote files + fakeFolder.remoteModifier().mkdir("A"); + fakeFolder.remoteModifier().mkdir("A/Sub"); + fakeFolder.remoteModifier().mkdir("A/Sub/SubSub"); + fakeFolder.remoteModifier().mkdir("A/Sub2"); + fakeFolder.remoteModifier().mkdir("B"); + fakeFolder.remoteModifier().mkdir("B/Sub"); + fakeFolder.remoteModifier().insert("A/a1"); + fakeFolder.remoteModifier().insert("A/a2"); + fakeFolder.remoteModifier().insert("A/Sub/a3"); + fakeFolder.remoteModifier().insert("A/Sub/a4"); + fakeFolder.remoteModifier().insert("A/Sub/SubSub/a5"); + fakeFolder.remoteModifier().insert("A/Sub2/a6"); + fakeFolder.remoteModifier().insert("B/b1"); + fakeFolder.remoteModifier().insert("B/Sub/b2"); + QVERIFY(fakeFolder.syncOnce()); + QVERIFY(fakeFolder.currentLocalState().find("A/a1.owncloud")); + QVERIFY(fakeFolder.currentLocalState().find("A/a2.owncloud")); + QVERIFY(fakeFolder.currentLocalState().find("A/Sub/a3.owncloud")); + QVERIFY(fakeFolder.currentLocalState().find("A/Sub/a4.owncloud")); + QVERIFY(fakeFolder.currentLocalState().find("A/Sub/SubSub/a5.owncloud")); + QVERIFY(fakeFolder.currentLocalState().find("A/Sub2/a6.owncloud")); + QVERIFY(fakeFolder.currentLocalState().find("B/b1.owncloud")); + QVERIFY(fakeFolder.currentLocalState().find("B/Sub/b2.owncloud")); + QVERIFY(!fakeFolder.currentLocalState().find("A/a1")); + QVERIFY(!fakeFolder.currentLocalState().find("A/a2")); + QVERIFY(!fakeFolder.currentLocalState().find("A/Sub/a3")); + QVERIFY(!fakeFolder.currentLocalState().find("A/Sub/a4")); + QVERIFY(!fakeFolder.currentLocalState().find("A/Sub/SubSub/a5")); + QVERIFY(!fakeFolder.currentLocalState().find("A/Sub2/a6")); + QVERIFY(!fakeFolder.currentLocalState().find("B/b1")); + QVERIFY(!fakeFolder.currentLocalState().find("B/Sub/b2")); + + + // Download All file in the directory A/Sub + // (as in Folder::downloadVirtualFile) + fakeFolder.syncJournal().markVirtualFileForDownloadRecursively("A/Sub"); + + QVERIFY(fakeFolder.syncOnce()); + QVERIFY(fakeFolder.currentLocalState().find("A/a1.owncloud")); + QVERIFY(fakeFolder.currentLocalState().find("A/a2.owncloud")); + QVERIFY(!fakeFolder.currentLocalState().find("A/Sub/a3.owncloud")); + QVERIFY(!fakeFolder.currentLocalState().find("A/Sub/a4.owncloud")); + QVERIFY(!fakeFolder.currentLocalState().find("A/Sub/SubSub/a5.owncloud")); + QVERIFY(fakeFolder.currentLocalState().find("A/Sub2/a6.owncloud")); + QVERIFY(fakeFolder.currentLocalState().find("B/b1.owncloud")); + QVERIFY(fakeFolder.currentLocalState().find("B/Sub/b2.owncloud")); + QVERIFY(!fakeFolder.currentLocalState().find("A/a1")); + QVERIFY(!fakeFolder.currentLocalState().find("A/a2")); + QVERIFY(fakeFolder.currentLocalState().find("A/Sub/a3")); + QVERIFY(fakeFolder.currentLocalState().find("A/Sub/a4")); + QVERIFY(fakeFolder.currentLocalState().find("A/Sub/SubSub/a5")); + QVERIFY(!fakeFolder.currentLocalState().find("A/Sub2/a6")); + QVERIFY(!fakeFolder.currentLocalState().find("B/b1")); + QVERIFY(!fakeFolder.currentLocalState().find("B/Sub/b2")); + + // Add a file in a subfolder that was downloaded + // Currently, this continue to add it as a virtual file. + fakeFolder.remoteModifier().insert("A/Sub/SubSub/a7"); + QVERIFY(fakeFolder.syncOnce()); + QVERIFY(fakeFolder.currentLocalState().find("A/Sub/SubSub/a7.owncloud")); + QVERIFY(!fakeFolder.currentLocalState().find("A/Sub/SubSub/a7")); + + // Now download all files in "A" + fakeFolder.syncJournal().markVirtualFileForDownloadRecursively("A"); + QVERIFY(fakeFolder.syncOnce()); + QVERIFY(!fakeFolder.currentLocalState().find("A/a1.owncloud")); + QVERIFY(!fakeFolder.currentLocalState().find("A/a2.owncloud")); + QVERIFY(!fakeFolder.currentLocalState().find("A/Sub/a3.owncloud")); + QVERIFY(!fakeFolder.currentLocalState().find("A/Sub/a4.owncloud")); + QVERIFY(!fakeFolder.currentLocalState().find("A/Sub/SubSub/a5.owncloud")); + QVERIFY(!fakeFolder.currentLocalState().find("A/Sub2/a6.owncloud")); + QVERIFY(!fakeFolder.currentLocalState().find("A/Sub/SubSub/a7.owncloud")); + QVERIFY(fakeFolder.currentLocalState().find("B/b1.owncloud")); + QVERIFY(fakeFolder.currentLocalState().find("B/Sub/b2.owncloud")); + QVERIFY(fakeFolder.currentLocalState().find("A/a1")); + QVERIFY(fakeFolder.currentLocalState().find("A/a2")); + QVERIFY(fakeFolder.currentLocalState().find("A/Sub/a3")); + QVERIFY(fakeFolder.currentLocalState().find("A/Sub/a4")); + QVERIFY(fakeFolder.currentLocalState().find("A/Sub/SubSub/a5")); + QVERIFY(fakeFolder.currentLocalState().find("A/Sub2/a6")); + QVERIFY(fakeFolder.currentLocalState().find("A/Sub/SubSub/a7")); + QVERIFY(!fakeFolder.currentLocalState().find("B/b1")); + QVERIFY(!fakeFolder.currentLocalState().find("B/Sub/b2")); + + // Now download remaining files in "B" + fakeFolder.syncJournal().markVirtualFileForDownloadRecursively("B"); + QVERIFY(fakeFolder.syncOnce()); + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } }; QTEST_GUILESS_MAIN(TestSyncVirtualFiles) |