Virtual Files: Allow to download a folder recursively from the socket API

Issue: #6466
This commit is contained in:
Olivier Goffart 2018-05-28 14:49:02 +02:00 committed by Olivier Goffart
parent 104f8c9ba2
commit 1753ce651b
6 changed files with 139 additions and 7 deletions

View File

@ -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);

View File

@ -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();

View File

@ -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();

View File

@ -242,6 +242,9 @@ public:
*/
void registerFolderWatcher();
/** new files are downloaded as virtual files */
bool useVirtualFiles() { return _definition.useVirtualFiles; }
signals:
void syncStateChange();
void syncStarted();

View File

@ -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)

View File

@ -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)